Published on InterSystems Developer Community (https://community.intersystems.com)

ホーム > データ変更の追跡 - 監査ログ - (2/2)

記事
Toshihiko Minamoto · 2021年1月11日 4m read

データ変更の追跡 - 監査ログ - (2/2)

前回の記事では、データの変更を簡単に記録できる方法をお見せしました。 今回は、監査ログが記録されるデータ構造と監査データを記録する「Audit Abstract クラス」を変更しました。

また、データ構造は親構造と子構造に変更し、それぞれに「トランザクション」とそのトランザクションで「その値によって変更されたフィールド」を記録するテーブルが 2 つ設けられます。

新しいデータモデルをご覧ください。

「監査クラス」から変更したコードをご覧ください。

Class Sample.AuditBase [ Abstract ]
{

Trigger SaveAuditAfter [ CodeMode = objectgenerator, Event = INSERT/UPDATE, Foreach = row/object, Order = 99999, Time = AFTER ]
{
#dim %compiledclass As %Dictionary.CompiledClass
#dim tProperty As %Dictionary.CompiledProperty
#dim tAudit As Sample.Audit

Do %code.WriteLine($Char(9)_"; get username and ip adress")
Do %code.WriteLine($Char(9)_"Set tSC = $$$OK")
Do %code.WriteLine($Char(9)_"Set tUsername = $USERNAME")

Set tKey = ""
Set tProperty = %compiledclass.Properties.GetNext(.tKey)
Set tClassName = %compiledclass.Name

Do %code.WriteLine($Char(9)_"Try {")
Do %code.WriteLine($Char(9,9)_"; Check if the operation is an update - %oper = UPDATE")
Do %code.WriteLine($Char(9,9)_"if %oper = ""UPDATE"" { ")

Do %code.WriteLine($Char(9,9,9)_"Set tAudit = ##class(Sample.Audit).%New()")
Do %code.WriteLine($Char(9,9,9)_"Set tAudit.Date = +$Horolog")
Do %code.WriteLine($Char(9,9,9)_"Set tAudit.UserName = tUsername")
Do %code.WriteLine($Char(9,9,9)_"Set tAudit.ClassName = """_tClassName_"""")
Do %code.WriteLine($Char(9,9,9)_"Set tAudit.Id = {id}")
Do %code.WriteLine($Char(9,9,9)_"Set tSC = tAudit.%Save()")
do %code.WriteLine($Char(9,9,9)_"If $$$ISERR(tSC) $$$ThrowStatus(tSC)")
Do %code.WriteLine($Char(9,9,9)_"Set tAuditId = tAudit.%Id()")

While tKey '= "" {
set tColumnNbr = $Get($$$EXTPROPsqlcolumnnumber($$$pEXT,%classname,tProperty.Name))
Set tColumnName = $Get($$$EXTPROPsqlcolumnname($$$pEXT,%classname,tProperty.Name))

If tColumnNbr '= "" {

Do %code.WriteLine($Char(9,9,9)_";")
Do %code.WriteLine($Char(9,9,9)_";")
Do %code.WriteLine($Char(9,9,9)_"; Audit Field: "_tProperty.SqlFieldName)
Do %code.WriteLine($Char(9,9,9)_"if {" _ tProperty.SqlFieldName _ "*C} {")

Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField = ##class(Sample.AuditField).%New()")
Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField.Field = """_tColumnName_"""")
Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField.OldValue = {"_tProperty.SqlFieldName_"*O}")
Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField.NewValue = {"_tProperty.SqlFieldName_"*N}")
Do %code.WriteLine($Char(9,9,9,9)_"Do tAuditField.AuditSetObjectId(tAuditId)")
Do %code.WriteLine($Char(9,9,9,9)_"Set tSC = tAuditField.%Save()")
do %code.WriteLine($Char(9,9,9,9)_"If $$$ISERR(tSC) $$$ThrowStatus(tSC)")
Do %code.WriteLine($Char(9,9,9)_"}")
}
Set tProperty = %compiledclass.Properties.GetNext(.tKey)
}

Do %code.WriteLine($Char(9,9)_"}")

Do %code.WriteLine($Char(9)_"} Catch (tException) {")

Do %code.WriteLine($Char(9,9)_"Set %msg = tException.AsStatus()")
Do %code.WriteLine($Char(9,9)_"Set %ok = 0")
Do %code.WriteLine($Char(9)_"}")

Set %ok = 1
}

}

Test() クラスメソッドを使ってデータを変更することで、Audit クラス (Sample.Audit) から「parent record」が見えるようになり、「children fields」も「Audit Field」クラスから変更されていることが分かります。 (Sample.AuditField)

d ##class(Sample.Person).Test(1)
INSERT INTO Sample.Person (Name, Age) VALUES ('TEST PARENT-CHILD', '01')
SQLCODE: 0

ID Age Name
1 01 TEST PARENT-CHILD

1 Rows(s) Affected

UPDATE Sample.Person SET Name = 'INTERSYSTEMS DEVELOPER COMMUNITY', Age = '100' WHERE Name = 'TEST PARENT-CHILD'
SQLCODE:0

ID Age Name
1 100 INTERSYSTEMS DEVELOPER COMMUNITY

1 Rows(s) Affected

<p>
  監査クラス: 
</p>

<p style="margin-left: 40px;">
  <img alt="" src="/sites/default/files/inline/images/image9.png" />
</p>

<p style="margin-left: 40px;">
  <img alt="" src="/sites/default/files/inline/images/image10.png" />
</p>

<p>
  Sample.AuditField の記録には、監査フィールド = 1 を使った Sample.Audit クラスへの参照があります。 以下に示すように、両クラスの関係を使えば、データに対してクエリを実行できます。
</p>

<p>
  <img alt="" src="/sites/default/files/inline/images/image11.png" />
</p>

これで完了です。 結果として、最初とは異なるログデータ構造ができました。

#ObjectScript #オブジェクトデータモデル #Caché

ソースURL:https://jp.community.intersystems.com/post/%E3%83%87%E3%83%BC%E3%82%BF%E5%A4%89%E6%9B%B4%E3%81%AE%E8%BF%BD%E8%B7%A1-%E7%9B%A3%E6%9F%BB%E3%83%AD%E3%82%B0-22