トリガの特殊変数( Intrinsic Special Variables ) ISV

GT.Mには、トリガー操作を容易にするための 9つのISV(Intrinsic Special Variables)が用意されています。$ZTWORMHOLEを除き、すべての数値トリガ関連のISVはトリガ・コンテキスト外でゼロ(0)を返します; 非数値ISVは空の文字列を返します。

$ZTDAta

トリガ・コンテキスト内で、$ZTDATA は、明示的な更新の前に、KILL、ZKILL、ZWITHDRAW の $DATA(@$REFERENCE)#2をSETまたは$DATA(@$REFERENCE)に返します。これは、トリガーコードでの間接参照の必要性を回避し、トリガ・コードがトリガ更新の前にトリガ・ノードの特性を決定するのを助ける高速パスの代替手段を提供します。SETの場合、ノードがデータを保持したか保持しなかったかを示します - SETが既存のノードの内容を変更しているか、新しいノードにデータを作成しているかどうか。KILLの場合、ノードに子孫があったかどうか、およびデータがあるかどうかが示されます。

$ZTDElim

SETトリガ・コンテキスト内で、$ZTDE[LIM] はトリガ定義の -delim で指定された区切り文字を返します。これによりトリガは区切り文字をルーチンにハードコードすることなく、$ZTUPDATEで定義された更新された部分文字を抽出することができます。SETトリガ・コンテキストの外側では、$ZTDELIM は nullです。

$ZTLevel

トリガ・コンテキスト内では、$ZTLEVEL はトリガ・ネストの現在のレベル(トリガコンテキストの更新によって追加のトリガのトリガによる呼び出し)を返します。

$ZTLEVEL が 1より大きい(>1) 場合は、進行中のネストされたトリガがあることを示します。1回の更新で複数のトリガが呼び出された場合、最初の(トリガではない)更新の複数のトリガが一致するため、それらはネストされていない(チェーンされている)ため、すべて同じ$ZTLEVELを持ちます。

例:

+^Cycle(1) -commands=Set -xecute="Write ""$ZTLevel for ^Cycle(1) is: "",$ZTLevel Set ^Cycle(2)=1"
+^Cycle(2) -commands=Set -xecute="Write ""$ZTLevel for ^Cycle(2) is: "",$ZTLevel Set ^Cycle(1)=1"

これらのトリガー定義は、2つのトリガーが再帰的(と病理学的)に呼び出されたときに、異なる値の$ZTLEVELを表示します。

+^Acct("ID") -commands=set -xecute="set ^Acct(1)=$ztvalue+1"
+^Acct(sub=:) -command=set -xecute="set ^X($ztvalue)=sub" 

SET ^Acct("ID")=10は上記のトリガーを何らかの順序で起動し、$ZTLEVELは両方とも同じ値を持ちます。なぜなら、これらのトリガーはネストされているのではなく連結されているからです。

$ZTNAME

トリガ・コンテキスト内で、$ZTNAMEはトリガ名を返します。$ZTNAMEは、トリガ・コンテキストの外側で空の文字列を返します。

$ZTOLdval

トリガ・コンテキスト内では、$ZTOLDVALは、更新がトリガ呼び出しを引き起こしたグローバル・ノードの以前の(古い)値を戻します。これは、トリガ・エントリ(ヘビー・ウェイトな間接指定を避ける) で $GET(@ $REFERENCE)に代わる高速パスを提供します。同じノード(連鎖)に一致するトリガが複数ある場合、$ZTOLDVALはそれらのそれぞれに対して同じ結果を返します。

例:

+^Acct(1,"ID") -commands=Set -xecute="Write:$ZTOLdval ""The prior value of ^Acct(1,ID) was: "",$ZTOLdval" 

このトリガーはSETで呼び出され、^Acct(1,"ID") の以前の値(存在する場合)を表示します。

GTM>w ^Acct(1,"ID")       
1975
GTM>s ^Acct(1,"ID")=2011
The prior value of ^Acct(1,ID) was: 1975

$ZTRIggerop

トリガー・コンテキスト内で、SET(MERGEと$INCREMENT()操作を含む) の場合、$ZTRIGGEROPの値は "S" です。KILLの場合、$ZTRIGGEROP の値は "K"です。ZKILLまたはZWITHDRAWの場合、$ZTRIGGEROPの値は "ZK" です。

$ZTSlate

$ZTSLATE は、一番外側のトランザクション(TSTART が $TLEVELを0から1に取るとき)のために呼び出される連鎖またはネストされたトリガで使用可能にする文字列を指定できます。$ZTOLDVALや$ZTVALUEなどのトランザクション関連情報を蓄積するために$ZTSLATEを使用すると、後で同じトランザクションで後続のトリガーで使用するためにトリガー・コンテキスト内で使用できます。たとえば、$ZTSLATEを使用して、トランザクションがコミットしようとしているときに書き込まれるアプリケーション履歴またはジャーナル・レコードを構築することができます。

SET $ZTSLATEは、データベース・トリガーがアクティブである間のみ設定できます。GT.Mは、最も外側のトランザクションまたはTRESTARTに対して$ZTSLATEをクリアします。ただし、GT.Mはすべてのサブトランザクション($TLEVEL> 1)に対して$ZTSLATEを保持します。

例:

 TSTART ()       ; Implicitly clears $ZTSLAT
 SET ^ACC(ACN1,BAL)=AMT          ; Trigger sets $ZTSLATE=ACN_"|"
 SET ^ACC(ACN2,BAL)=-AMT         ; Trigger sets $ZTSLATE=$ZTSLATE_ACN_"|"
 ZTRIGGER ^ACT("TRANS")          ; Trigger uses $ZTSLATE to update transaction log
 TCOMMIT

$ZTUPdate

トリガ・コンテキスト内で、GT.Mトリガが区切り文字を指定するSETコマンドの場合、$ZTUPDATEは、$ZTOLDVAL と $ZTVALUEの現在の値の間で異なる部分文字の個数のカンマ区切りのリストを提供します。トリガがピースセパレータを指定しているが、関心のある部分を指定していない場合、$ZTUPDATEはすべての変更された部分文字を識別します。それ以外の場合は、$ZTUPDATEが0になります(すなわち:GT.Mトリガで区切り文字が指定されていないSETコマンドやKILLの場合)。もし更新が複数のトリガと一致する場合、一致するすべてのトリガは、トリガ・エントリの時点で同じ $ZTOLDVALを参照しますが、潜在的には異なる $ZTVALUEの値を参照するため、たとえ一致するすべてのトリガが同じ -[z]delim と -piece 仕様を持ってたとしても、一致する各トリガのアクションによって$ ZTUPDATEが変更される可能性があります。

例:

+^trigvn -commands=Set -pieces=1;3:6 -delim="|" -xecute="Write !,$ZTUPDATE" 

上記のトリガ定義エントリでは、$ZTUPDATEは、変更された部分文字の番号のカンマ区切りのリストを表示します: 1,3,4,5,6 が更新によって変更されます。

GTM>write ^trigvn
Window|Table|Chair|Curtain|Cushion|Air Conditioner
GTM>set ^trigvn="Window|Dining Table|Chair|Vignette|Pillow|Air Conditioner"
4,5 

部分文字の番号 2, 4, 5 が変更されても、$ZTUPDATE は、2番目の部分文字の更新にトリガが定義されていないため、4,5 のみを表示します。

$ZTVAlue

SETの場合、$ZTVALUEは、明示的なSET操作によってノードに割り当てられた値を持ちます。トリガ内の$ZTVALUEを変更すると、GT.Mがノードに割り当てる最終的な値が変更されます。$ZTVALUEを変更すると、すべてのトリガ・コードが完了した後にノードで追加の更新操作が行われるため、パフォーマンスへの影響はわずかです。ノードに複数の関連トリガがある場合、各トリガは現在の$ZTVALUEの値を受け取りますが、トリガは任意の順序で実行されるため、FISではアプリケーションデータの任意の要素を変更することを強く推奨しません。KILLとその変形では、$ZTVALUEは空の文字列を返します。GT.Mは、KILLまたはその変形のために呼び出されるトリガ・コード内で$ZTVALUEへの更新を受け入れますが、最終的にはそのような値は破棄されます。トリガ・コンテキスト外で、SET $ZTVALUEを試行すると、SETINTRIGONLYエラーが発生します。

$ZTWOrmhole

$ZTWORMHOLEでは、トリガの実行中に利用可能にしたい情報を最大128KBの文字列で指定することができます。$ZTWORMHOLEを使用して、アプリケーション・コンテキストまたはプロセス・コンテキストをトリガ・ロジックに供給することができます。GT.Mは処理中の間ずっと$ZTWORMHOLEを利用可能にするので、$ZTWORMHOLEにアクセスしたり更新したりすることができます。

$ZTWORMHOLEは、トリガ・コンテキストでは使用できない別の方法でプロセス/アプリケーションのコンテキストからの情報にアクセスするためのメカニズムを提供します。GT.Mは、$ZTWORMHOLEを参照する少なくとも1つのトリガを呼び出す更新の一部として、$ZTWORMHOLEの空でない文字列値をGT.Mデータベース・ジャーナル・ファイルに記録します。GT.Mは、レプリケーション・ストリーム内にNULL以外の$ZTWORMHOLE値も送信し、MUPIPプロセスによって呼び出されるトリガに同じコンテキストを提供します(レプリケーション・インスタンス更新プロセスの一部として、またはMUPIP journal recovery/rollback の一部として)。したがって、トリガで$ZTWORMHOLEを使用するたびに、プロセス・コンテキストのワームホールのようなものが作成されます。これは、実行時にNEWされるか、MUPIPには存在しません。

トリガコードが$ ZTMORMHOLEを参照していない場合、GT.Mは(ジャーナル・ファイルまたはレプリケーション・ストリームを介して)MUPIPで使用できるようにしません。したがって、レプリケートを受けるセカンダリが起動プライマリとは異なるトリガコード(珍しい設定)を持ち、レプリケート・ノード上のトリガに$ZTWORMHOLEの情報が必要な場合、起動ノードのトリガは $ZTWORMHOLEを参照してGT.Mがデータを保持するようにする必要があります。 それは、複製ノード上の更新プロセスにより使用されることを含みます。トリガ・コード内で$ZTWORMHOLEを変更することはできますが、同じノード上でトリガを任意の順序で並べるため、慎重な設計と実装のアプローチが必要です。GTMは$ZTWORMHOLEをNEWにすることができます。$ZTWORMHOLEをNEWすることは、前者がオリジナルの値を保持し、後者がオリジナルの値を保持するという意味で、他のISV/変数をNEWすることとは若干異なります。しかし、他のNEWと同様に、GT.Mはスタック・レベルがポップアップするときに$ZTWORMHOLEの値を復元します。

次の表は、トリガ・コンテキスト内および外部トリガ・コンテキスト内のすべてのトリガ関連ISVに割り当てられた読み取り/書き込み許可をまとめたものです。

固有の特殊変数

トリガ・コンテキストの中で

注意点

$ETRAP

読み / 書き

トリガコンテキストに入るときは、gtm_trigger_etrapまたは空文字列に設定トリガの実行中にエラーを処理するための$ETRAPメカニズムの使用の詳細については、 “トリガ実行中のエラー処理”を参照してください。

$REFERENCE

読み取り専用

トリガの完了時に復元

$TEST

読み取り専用

トリガの完了時に復元

$TLEVEL

読み取り専用

トリガコードで常に >=1 ; 開始時のトリガーの処理完了と同じでなければなりません。

$ZTNAME

読み取り専用

トリガ名を返します。

$ZTDATA

読み取り専用

以前の状態を示します。

$ZTLEVEL

読み取り専用

トリガ・ネストを表示します。

$ZTOLDVAL

読み取り専用

更新前の値を表示します。

$ZTRAP

読み取り専用 - ""

トリガ・コードで $ETRAPを使用する必要があります。

$ZTRIGGEROP

読み取り専用

トリガ・コマンドを表示します。

$ZTUPDATE

読み取り専用

SETの変更された部分(要求されている場合)を一覧を表示

$ZTVALUE

読み / 書き

SETの最終的な適用値を変更することができます。

$ZTWORMHOLE

読み / 書き

トリガ・コードにローカル変数コンテキストへのアクセスがないため、アプリケーション・コンテキストを保持します。

$ZTSLATE

読み / 書き

連鎖またはネストされたトリガの最も外側のトランザクション・コンテキストを保持します。

トリガISVsの例

>

以下の例は、FISプロファイル・アプリケーションから得られたものです。

^ACN(CID,50) のノードは、部分文字列1にTYPE、部分文字列2にCLS、部分文字列15にFEEPLN、部分文字列31にEMPLNOを持ちます。インデックスは ^XACN(CLS,ACN,CID)、^XREF("EMPLCTA",EMPLNO,ACN,TYPE,CID)と^XREF("FEEPLN",FEEPLN,CID)を使用し、^ACN(CLS,99)の最初の部分文字列からACNを使用します。これらのインデックスは、^ACN(:,50)のノードのKILLまたはZKillによって呼び出され、SETによって3つの^ACN(:,50)ノードに呼び出される3つのトリガーで維持されます。EMPLNOとFEEPLNはNULLにすることができますが、ACN、CID、CLS、およびTYPEは必須ですが、インデックスでは$ZC(254)の使用が必要です。トリガ・ファイルの定義は次のとおりです:

+^ACN(cid=:,50) -zdelim="|" -pieces=2 -commands=SET -xecute="Do ^SclsACN50"  
+^ACN(cid=:,50) -zdelim="|" -pieces=1,31 -commands=SET -xecute="Do ^SemplnoTypeACN50" +^ACN(cid=:,50) -zdelim="|" -pieces=15 -commands=SET -xecute="Do ^SfeeplnACN50" 
+^ACN(cid=:,50) -commands=KILL,ZKill -xecute="Do ^KACN50" 

KACN50.m のコードは、アプリケーションが任意の^ACN(:,50)を削除するときに相互参照インデックスをKILLします。

KACN50 ; KILL of entire ^ACN(:,50) node, e.g., from account deletion
  ; Capture information
  Set cls=$Piece($ZTOLD,"|",2)                   ; CLS
  Set emplno=$Piece($ZTOLD,"|",31)
  Set:'$Length(emplno) emplno=$ZC(254)                ; EMPLNO
  Set feepln=$Piece($ZTOLD,"|",15)
  Set:'$L(feepln) feepln=$ZC(254)                     ; FEEPLN
  Set type=$Piece($ZTOLD,"|",1)                  ; TYPE
  Set acn=$Piece(^ACN(cid,99),"|",1)             ; ACN
  Kill ^XACN(cls,acn,cid)
  Kill ^XREF("EMPLCTA",emplno,acn,type,cid)
  Kill ^XREF("FEEPLN",feepln,cid)
  Quit

SclsACN50.m のルーチンは、SETの相互参照、または ^ACN(:,50)の2番目の部分を変更するSET $PIECE()を作成します。

SClsACN50 ; Update to CLS in ^ACN(,50)
 ; Capture information
  Set oldcls=$Piece($ZTOLD,"|",2)                ; Old CLS
  Set cls=$Piece($ZTVAL,"|",2)                   ; New CLS
  Set acn=$Piece(^ACN(cid,99),"|",1)             ; ACN
  Set processMode=$Piece($ZTWORM,"|",1)          ; Process
  If processMode<2 Kill ^XACN(oldcls,acn,cid)
  Set ^XACN(cls,acn,cid)=""
  Quit 

この例はわかりやすくするために書かれていることに注意してください。一時的なローカル変数に代入する必要がない値を削除すると、次のような結果が得られます:

SclsACN50
  S acn=$P(^ACN(cid,99),"|",1)
  I $P($ZTWORM,"|",1)<2 K ^XACN($P($ZTOLD,"|",2),acn,cid)
  S ^XACN($P($ZTVAL,"|",2),acn,cid)=""
  Q

実際、このインデックスは、(1行の)トリガ・ファイル仕様自体に単純に含めることができます:

+^ACN(cid=:,50) -zdelim="|" -pieces=2 -commands=SET -xecute="S oldcls=$P($ZTOLD,""|"",2),acn=$P(^ACN(cid,99),""|"",1) K:$P($ZTWO,""|"",1)<2 ^XACN(oldcls,acn,cid) S ^XACN($P($ZTVAL,""|"",2),acn,cid)="""""

読みやすくするために、この章のほとんどのトリガ・ファイル定義は完全なルーチンとして記述されています。SemplnoTypeACN50.mのコードは、^ACN(:,50) の1と31の部分の変更を処理します。どちらかまたは両方のピースを変更する ^ACN(:,50) へのSETは、このトリガーを1回だけ実行しますが、ところが2つの連続した SET $Piece() コマンドは、最初に1つの部分文字列を修正し、次に、もう1つは異なる時点に2回、各部分に対して1回ずつ実行させます。

EmplnoTypeACN50 ; Update to EMPLNO and/or TYPE in ^ACN(,50)
 ; Capture information
  Set oldemplno=$Piece($ZTOLD,"|",31)
  Set:'$Length(oldemplno) oldemplno=$ZC(254)
  Set emplno=$Piece($ZTVAL,"|",31)
  Set:'$L(emplno) emplno=$ZC(254)
  Set oldtype=$Piece($ZTOLD,"|",1)
  Set type=$Piece($ZTVAL,"|",1)
  Set acn=$Piece(^ACN(cid,99),"|",1)
  Set processMode=$Piece($ZTWORM,"|",1)
  If processMode<2 Do
  . Kill ^XREF("EMPLNO",oldemplno,acn,oldtype,cid)
  . Set ^XREF("EMPLNO",emplno,acn,type,cid)=""
  Quit

SFeeplnACN50.m のコードは、15番目の部分への変更を処理します。

SFeeplnACN50 ; Update to FEEPLN in ^ACN(,50)
  ; Capture information
  Set oldfeepln=$Piece($ZTOLD,"|",15)
  Set:'$Length(oldfeepln) oldfeepln=$ZC(254)
  Set feepln=$Piece($ZTVAL,"|",15)
  Set:'$Length(feepln) feepln=$ZC(254)
  Set processMode=$Piece($ZTWORM,"|",1)
  If processMode<2 Do
  . Kill ^XREF("FEEPLN",oldfeepln,cid) Set ^XREF("FEEPLN",feepln,cid)=""
  Quit 
inserted by FC2 system