トリガ技術情報


Copyright © 2010 Fidelity Information Services, Inc. All rights reserved.

Free Software Foundationによって公開されているGNU Free Documentation License, Version1.3 またはそれ以降のバージョンで同意されたものとして、本マニュアルの修正版の複写と配布は、修正版全体が本許可告知と同一の条件のもとに配布される場合にのみ許可します。但し、「変更不可能部分」「おもて表紙テキスト」「うら表紙テキスト」など変更不可部分は含みません。

GT.M™ は、Fidelity Information Services, Inc. のトレードマークです。その他商標は、それぞれの所有者の所有物です。

このドキュメントでGT.Mの説明および操作方法は、システムを構成するさまざまな機能に関するものが含まれます。このドキュメントには、FISのコミットメントは何も含まれていません。FISは、この文書の情報は発表日現在において正確であると考えていますが、情報は予告なしに変更される場合があります。FISのすべてのエラーまたは欠陥について責任は負いません。

改訂履歴

バージョン

日付

サマリ

1.1 2010年7月13日
Updated to reflect the trigger enhancements released with GT.M V5.4-001. Reworked the Overview and Trigger Definition File section. Added a new section called "Chained and Nested Triggers". Added V5.4-001 Triggers-related error messages. Miscellaneous cleanup of vocabulary and grammar. Improved content organization and presentation.

All significant changes are marked in "blue" color.

1.0

2010年2月2日

最初の公開バージョン

 

連絡先情報


GT.Mグループ
FIS
2 West Liberty Boulevard, Suite 300
Malvern, Pennsylvania 19355
アメリカ合衆国
GT.M Support for customers: +1 (610) 578-4226 / gtmsupport@fisglobal.com
Switchboard: +1 (610) 296-8877
Website: http://fis-gtm.com

目次

  1. トリガ技術情報
    1. 改訂履歴
    2. 連絡先情報
    3. 目次
    4. 概要
    5. トリガ定義ファイル
    6. トリガのISVs
    7. チェインとネストのトリガ
    8. 簡単な例
    9. トリガ定義の保存
    10. トリガ呼出と実行のセマンティクス
      1. Kill / ZKill
      2. Set
      3. トリガの実行環境
        1. トリガ実行中のエラー処理
        2. ZGOTO
      4. GT.CM
      5. その他のユーティリティ
    11. ジャーナリングとデータベースのレプリケーションのトリガー
      1. ジャーナリング
        1. MUPIP JOURNAL -RECOVER / -ROLLBACK
      2. マルチサイトのデータベース レプリケーション
        1. インスタンスに別のトリガ設定でレプリケート
        2. サポートしていないインスタンスにレプリケートトリガー
      3. アップデートとヘルパープロセス
    12. MUPIP TRIGGER and $ZTRIGGER()
      1. MUPIP トリガ
        1. TRIGgerfile
        2. SELEct
        3. MUPIPトリガーの例
      2. $ZTRIGGER
        1. $ZTRIGGERの例は
    13. ISVs and Environment Variables
      1. $ZTCOde
      2. $ZTDAta
      3. $ZTLevel
      4. $ZTOLdval
      5. $ZTRIggerop
      6. $ZTSlate
      7. $ZTUPdate
      8. $ZTVAlue
      9. $ZTWOrmhole
      10. トリガISVsの例
    14. トリガエラーメッセージ
      1. GVDATAGETFAIL
      2. NOZTRAPINTRIG
      3. SETINTRIGONLY
      4. TRIG2NOTRIG
      5. TRIGCOMPFAIL
      6. TRIGDATAIGNORE
      7. TRIGDEFBAD
      8. TRIGINVCHSET
      9. TRIGJNLSTATE
      10. TRIGNAMEUNIQ
      11. TRIGSUBSCRANGE
      12. TRIGTCOMMIT
      13. TRIGTLVLCHNG
      14. ZGOTOINVLVL
      15. ZTRIGINVACT
      16. ZTRIGNOTP
      17. ZTWORMHOLE2BIG

概要

V5.4 - 000以降で、GT.Mは、一致するグローバルノード上で、データベースの更新操作に応じて、定義されたアクションを自動的に実行するトリガ機構を設定することができます。

トリガのメカニズムは、Mコード(トリガコード)の断片を実行する、、、"前"または"データベースの更新"の一環として。 トリガ定義ファイル と呼ばれるファイル内でこのメカニズムの記述を定義できます。

KILL(ZKILL)のトリガで、GT.Mは、KILL操作の前に、トリガのコードを実行します。たとえば、KILL ^CIF(:,1)のトリガは、自動的に古いクロスリファレンスをクリアすることがあります。

セットでのトリガで、GT.Mは、SET操作の一部として、トリガのコードを実行します。トリガロジック内で、ISV $ZTOLDVAL は、更新より先にグローバルノードの値への読み取りアクセスを提供し、$ZTVALUE は、仮のSET値へのアクセスを読み書きします。これは、GT.Mがデータベースへそれをコミットする前に、仮のSET値を変更することを許可します。SETトリガがSET操作と密接に実行することは、その条件が " 一環"を意味します。まだデータベースをコミットされていないにもかかわらず、グローバルノードのSETは再帰的にトリガをネストするので(異常な状態)、仮の新しい値はアサインされたプロセスに現れますが、 プロセスは、仮の値に任意の改訂を作るために$ZTVALUE をSETしなければなりません。GT.Mは、SETはGT.Mは内部的に一方、$インクリメント()をGT.Mは、内部のSET操作を実行する操作を実行するのSET一連の操作を実行するのMERGE更新中にトリガを実行します。

すべてのトリガは、GT.Mは、データベースの更新イベントと原子(全か無か)トランザクション単位としてトリガーアクションを処理します。詳細については、"参照してくださいトリガ呼び出しと実行セマンティクス "。

トリガは、以下を含む、(ただし、限定されない)、さまざまな状況で使用することができます:   

トリガ定義ファイル

トリガの定義ファイルはテキストファイルで、新しいトリガを追加したり、既存のトリガの変更したり、トリガを廃止し撤去したりします。トリガの定義ファイルは、1つ以上のトリガの定義から成ります。トリガの定義は、次の情報が含まれます: 


An automatically generated trigger name is a string comprised of two parts. ベースとしてグローバル名を使用して、GT.Mは、アルファベット文字またはパーセント記号(%)で始まる21文字までの英数字文字列として最初の部分を取ります。The trailing part consists of an automatically incremented number in the form of #n where n is a whole number from 1 to 9999999 that uniquely identifies a trigger for the same update. For example, GT.M automatically generates trigger names Account#1, Account#2, and Account#3 for the first three triggers defined for global variable ^Account if no trigger names are specified in the trigger definition file. An attempt to use automatic assignment for more than a million triggers produces an error.

At run-time GT.M generates a trailing suffix of a hash-sign (#) followed by up to two characters to ensure that every trigger has a unique designation, even when the environment is complex. 実行時の接尾辞は、トリガ名がユーザ指定と自動生成の両方に適用されます。通常、この接尾辞を無視することができます。


Suppose you want to set up a trigger called TrigAcct on every s ^Acct("ID") to invoke the routine ^OpenAccount. Your trigger definition file may have an entry like +^Acct("ID") -command=S -xecute="do ^OpenAccount" -name=TrigAcct. The following diagram identifies the different parts of this trigger definition:



To apply this trigger definition file to GT.M, all you do is to load it using MUPIP TRIGGER -TRIGGERFILE or $ZTRIGGER(). GT.M would invoke trigger name TrigAcct on every Set operation on ^Acct("ID").  Internally, GT.M stores trigger TrigAcct in the same database file where ^Acct is stored. 

トリガ定義ファイル内のエントリの構文は次のとおりです: 
{-triggername|-triggername-prefix*|-*|{+|-}trigvn -commands=cmd[,...] -xecute=strlit1 [-[z]delim=expr][-pieces=[lvn=]int1[:int2][;...]] [-options={[no]i[solation]|[no]c[onsistencycheck]}...] [-name=strlit2]}

 
-triggername|-trigger-name-prefix*|-* -triggername deletes a user-specified trigger name called triggername from the database.  
-triggername* deletes all those user-defined triggers whose starting name match triggername.  
-* deletes all triggers; if the MUPIP TRIGGER command does not specify -NOPROMPT , GT.M displays a warning and asks for user confirmation before deleting all triggers. If MUPIP TRIGGER command specifies -NOPROMPT and the definition file includes a -* line, GT.M deletes all the triggers without user confirmation. $ZTRIGGER() performs deletions -NOPROMPT.  
+triggername issues an error; to add a new user-specified trigger name, use -name=strlit2.
{+|-}trigvn trigvn is a global node on which you set up a trigger.   
-trigvn deletes any triggers in the database that match the specified trigger.   
+trigvn adds or replaces the specified trigger.  If the specified trigger exists (with a matching specification), MUPIP TRIGGER or $ZTRIGGER() treats the matching definition as a no-op, resulting in no database update.  If you want to specify more than one global node for the same trigger code, the following rules apply:  
  • 添字のためのパターンと範囲を使用できます。
  • 添字のために、セミコロン(;) で区切られたリストを指定できます。
  • ポイント、範囲、パターンの組み合わせを含む選択リストを指定できますが、パターンは、範囲の両端で機能はできません。For example, :,"a":"d";?1U is a valid specification but :,"a":?1A is not. 
  • 各添字のローカル変数名を指定できます。For example instead of ^X(1,:,:), you can specify ^X(1,lastname=:,firstname=:). This causes GT.M to define local variables lastname and firstname to the actual second and third level subscripts respectively from the global node invoking this trigger. トリガコードは、ちょうど他のMローカル変数のように、これらの変数を使用できます。As described in the Trigger Execution Environment section, trigger code executes in a clean environment - as if all code is preceded by an implicit NEW – the implicit assignments apply only within the scope of the trigger code and don't conflict or affect any run-time code or other triggers.
  • You cannot use the @ operator, unspecified subscripts (for example, ^A() or ^A(:,)) or local or global variable names as subscripts.
  • グローバル変数名のパターンと範囲は使用できません。Therefore, you cannot set a trigger for ^Acct*.
いくつかの非標準の照合順序を考慮するには、アプリケーション更新が最初にトリガを起動する時に、GT.Mは、グローバル固有の照合順序を使用して、文字列の添字の範囲を評価します。結果として、それは、MUPIP TRIGGERまたは$ZTRIGGER() からではなく実行時に範囲の問題を検出し報告するので、適切にテストします。たとえば、GT.Mは、(ASCII)C:A のような反転する添字の範囲にランタイムエラーを報告します。  
-command=cmd cmd is the trigger invocation command. Currently, you can specify one or more of S[et], K[ill] or ZK[ill]. A subsequent GT.M release may support ZTK[ill] for triggering on descendent nodes of a KILLed ancestor, but, while current versions accept ZTK, they convert it into K.   If cmd specifies multiple command values, GT.M treats each M command as a separate trigger. Note that even if you specify both SET and KILL, only one M command matches at any given time. Trigger code is not executed in the following conditions:  
  • 存在しないノードのKILLの場合
  • A KILL of a node that has a cmd=ZK trigger, but no cmd=K trigger.
  • A ZKILL or ZWITHDRAW of a node that has descendents but no data and a trigger with cmd=ZK.
  • トリガは、 "piece" 構文(後述)を使用し、更新中にトリガ部分を変更しません。
  • The duplicate SET optimization is enabled (that is, the environment variable gtm_gvdupsetnoop is set to 1|True|Yes) and a SET command causes no change in the value of a preexisting node.  
-xecute="strlit1" strlit1 specifies the trigger code executed when an update matches the trigvn. Note that strlit1 is a quoted string literal and quotes inside strlit1 are doubled as in normal M syntax. 

To validate strlit1, MUPIP TRIGGER or $ZTRIGGER() compiles it before applying the trigger definition to the database and issues a TRGCOMPFAIL error if it contains any invalid code.

Note: Trigger compilation detects compilation errors, but not run-time errors. Therefore, you should always test your trigger code before applying trigger definitions to the database

Warning: As stated in the Trigger Definition File section, the text of trigger code is a part of the trigger signature. If you use two trigger signatures that have the same semantics (global variable, subscript, value, and command) but different text (for example: set foo=$ztoldval, s foo=$ztoldval, and set foo=$ztol), their signatures become different and GT.M treats them as different triggers. FIS recommends you to use comprehensive and strong coding conventions for trigger code or rely on user-specified names in managing the deletion and replacement of triggers.
[-pieces=int1[:int2][;...]]    

If cmd is S[et], you can specify an optional piece list sequence where int2>int1 and int1:int2 denotes a integer range from int1 to int2. 指定された部分リストの変更から任意の部分の場合のみ、トリガが実行されます。Suppose your trigvn has a list "Window|Chair|Table|Door" and you want to execute the trigger only when the value of the 3rd or 4th piece changes so you might specify the following trigger definition:  


+^trigvn -commands=S -pieces=3;4 -delim="|" -options=NOI,NOC -xecute="W ""3rd or 4th element updated."""
 
GTM>W ^trigvn
Window|Chair|Table|Door|
GTM>s $P(^trigvn,"|",3)="Dining Table"
3rd or 4th element updated.

もし最初の要素を変更した場合、このトリガは実行されません。次に例を示します。  

S $P(^trigvn,"|",1)="Chandelier"

トリガを呼び出しません。  


また、部分シーケンスの範囲を指定することもできます。たとえば、3:5;7;9:11 は3から5、7、9、11 でトリガを指定します。GT.Mは、任意の重複値または範囲をマージします - 例えば、 3:6;7 は 3:7と同じです。 

[-[z]delim=expr] If cmd is S[et], you can specify an optional piece delimiter using -[z]delim=expr where expr is a string literal or an expression (with very limited syntax) evaluating to a string separating the pieces (e.g., "|") in the values of nodes, and is interpreted as an ASCII or UTF-8 string based on the $gtm_chset environment variable.  To allow for unprintable delimiters in the delimiter expression, MUPIP TRIGGER only accepts  $Char() and $ZChar()  and string concatenation (_) as embellishments to the string literals.  If zdelim specifies a delimiter, GT.M uses the equivalent of $ZPiece() to match pieces and to identify changes in $ZTUPDATE() (refer to the ISV description for additional information); otherwise, if delim specifies a delimiter, GT.M uses the equivalent of $Piece() for the current mode (M or UTF-8). Specifying a delimiter for cmd other than S[et] or specifying both delim and zdelim for the same trigger each produce an error.
[-options={no]i[solation]|[[no]c[onsistencycheck]}... You can specify [NO] ISOLATION or [NO]CONSISTENCYCHECK as a property of the triggered database updates. NOISOLATION is a facility for your application to instruct GT.M where the application logic and database schema take responsibility for ensuring the ACID property of ISOLATION, and that any apparent collisions are purely coincidental from multiple global nodes resident in the same physical block which serves as the GT.M level of granularity in conflict checking. In the current release this trigger designation is notational only - you must still implement NOISOLATION at the process level with the VIEW command, but you can use the trigger designation in planning to move to schema-based control of this facility. NOCONSISTENCYCHECK is a facility for your application to instruct GT.M that application logic and schema take responsibility for ensuring the ACID property of CONSISTENCY. The [NO]CONSISTENCYCHECK feature is not yet implemented and will be made available in a future GT.M release. For now, you can plan to move CONSISTENCY responsibility from your application to a trigger and implement it later when this feature becomes available.

Note: -options are not part of the trigger signature and so can be modified without deleting an existing trigger.
[-name=strlit2] strlit2 is a user-specified trigger name. 28文字までの英数字文字列です。[参考] [参考] アルファベット文字またはパーセント記号(%)で始まる必要があります。

[参考] Note: -options are not part of the trigger signature and so can be modified without deleting an existing trigger.

Note also that the name can be used to delete a trigger - this alternative avoids potential issues with text variations in the code associated with the -xecute qualifier which is part of the trigger signature when the variations don't have semantic significance.
 

トリガのISVs

次の表は、簡単に使用する場合、すべてのISVを(組み込み特殊変数)を説明します。トリガを用いてアプリケーションロジックによって使用できる方法について説明します。$ZWORMHOLEを除いて、返すゼロ(0)は、数値値または空の文字列をコードでトリガの外側で参照されている場合コンテキスト。より包括的な説明と、これらのISVの使用例については、"参照してくださいトリガISVは "。

$ZTCODE
現在のトリガに対応するMコード(Xecute)文字列が含まれます。
$ZTDATA
SETのための$Data(@$REFERENCE)#2、または、KILLされるノードの$Data(@$REFERENCE)に替わるパス。
$ZTLEVEL
トリガのネストの現レベルを返します。(追加トリガのトリガコードでプログラムによって呼び出された)
$ZTOLDVAL
もしノードが値を持っていなかったなら、更新がトリガの起動または空の文字列を引き起こすノードの以前(旧)の値を返し;もしノードにデータ値があったなら$ZTDATAを参照します。
$ZTRIGGEROP
SET(MERGEと$INCREMENT() オペレーションを含む)では、$ZTRIGGEROPは、値 "S" を返します。KILLでは、$ZTRIGGEROPは、値 "K"を返します。ZKILL or ZWITHDRAW では、$ZTRIGGEROPは、値 "ZK"を返します。
$ZTSLATE
$ZTSLATEは、最も外側のトランザクションに呼び出されたチェーンまたはネストのトリガで利用したい文字列を指定できます(TSTARTが0から1の$TLEVELを取る時)。
$ZTVALUE
SETでは、$ZTVALUEは、トリガされた更新をノードに割り当てられている値を持ちます。当初、この値は(トリガしている)SETの操作を明示的に指定されます。トリガ内で$ZTVALUEの変更は、最終的にGT.Mがノードに割り当る値を変更します。
$ZTUPDATE
GT.Mトリガが部分文字の区切り記号を指定するSETコマンドでは、$ZTUPDATEは、現在の$ZTOLDVALと$ZTVALUEの値の間で異なる部分文字列の部分文字の序数番号のカンマ区切りのリストを提供します。
$ZTWORMHOLE
$ZTWORMHOLE allows you to specify a string up to 128KB  that you want to make available during trigger execution. You can use $ZTWORMHOLE to supply application context or process context to your trigger logic. $ZTWORMHOLEはプロセスの期間中ずっと保持されるので、内側からと外側の両方の$ZTWORMHOLE トリガ を読み取り/書き込みができます。もしトリガコードが$ZTWORMHOLEを参照していない場合は、GT.Mは、(ジャーナルファイルまたはレプリケーションストリームを介して)それをMUPIPへ利用できないようにすることに注意してください。したがって、もしレプリケーションのセカンダリが、$ZTWORMHOLEからの情報を必要とするレプリケーションのノード上で、開始しているプライマリ(珍しい構成)とトリガとは異なるトリガ コードを持っている場合、開始しているノード上のトリガは、それがレプリケーションノードの更新プロセスによって使用するために含まれているデータを、GT.Mが維持し確保するために、$ZTWORMHOLE を参照する必要があります。GT.M allows you to change $ZTWORMHOLE within trigger code so that a triggered update can trigger other updates  but because of the arbitrary ordering of triggers matching the same node (refer to the discussion on trigger chaining below), such an approach requires careful design and implementation.
   
The Trigger Execution Environment section describes the interactions of the following ISVs with triggers: $ETRAP, $REFERENCE, $TEST, $TLEVEL, and $ZTRAP.

チェインとネストのトリガ

データベースの更新が複数のトリガをオフに設定したときに、トリガがチェインまたはネストされます。ネストされたトリガは、別のトリガによってオフに設定したトリガです。GT.Mは、それぞれのネストされたトリガに、最大127レベルまでネストレベルを割り当てます。While nested triggers are always Atomic with their triggering update GT.M gives each nested trigger a new trigger context rather than a part of the triggering update. 

A chained trigger is an arbitrary sequence of matching triggers for the same database update.

Consider the following trigger definition entries:
 
+^Acct("ID") -commands=Set -xecute="Set ^Acct(1)=$ZTVALUE+1"
+^Acct(sub=:) -command=Set -xecute="Set ^X($ZTVALUE)=sub"
 
This example sets off a chained sequence of two triggers and one nested trigger. On Set ^Acct("ID")=10, GT.M chains together an arbitrary sequence of triggers for ^Acct("ID") and ^Acct(sub:). It is possible for either the ^Acct(sub=:) trigger or the ^Acct("ID") trigger to execute first and the other to follow because the trigger execution sequence is arbitrary. Whenever GT.M invokes the trigger for ^Acct("ID"), the Set ^Acct(1)=$ZTVALUE+1 code sets off the trigger for ^Acct(sub=:) as a nested trigger.

Caution: FIS recommends against using chained and nested triggers that potentially update the same piece of a global variable. You should always assess the significance of having chained triggers for a database update especially because of the arbitrary trigger execution order.

The following table shows the stacking behavior of some Intrinsic Special Variables in chained and nested triggers.

ISV(特殊変数)のスタッキング

チェイン

ネスト

$REFERENCE

共有

スタック

$TEST

スタック

スタック

$ZTVALUE

共有 (更新可能)

スタック

$ZTOLDVAL

共有

スタック

$ZTDATA

共有

スタック

$ZTSLATE
スタックしない
スタックしない

$ZTTRIGGEROP

共有

スタック

$ZTWORMHOLE

スタックしない

スタックしない

$ZTLEVEL

共有

スタック

$ZTUPDATE

トリガ起動時に $ZTVALUE に依存

スタック

 

Stacked denotes an ISV whose value is restored at the completion of the trigger.
Not Stacked denotes an ISV whole value is retained after the completion of the trigger.
Shared denotes an ISV whose value is the same, possibly subject to updates, across chained updates

ネストとチェインの両方があるトリガは、双方のカラム特性を持っていることに注意してください。- "チェイン" のカラムは、同じ更新によって呼び出されるトリガ同士のリレーションについて実際にあり、そして、そのコンテキストが別のトリガのコンテキスト内にあるかどうかにかかわらず、"ネスト"は、それを呼び出したコンテキストからのトリガの分離について実際にあります。

簡単な例

This section contains a simple example showing how a GT.M trigger can automatically maintain cross references in response to a SET or KILL operation on ^CIF(ACN,1).  It also reinforces the basic trigger concepts explained above.

Global nodes in ^CIF(ACN,1) have a structure ^CIF(ACN,1)=NAM|XNAME| where the vertical-bars are delimiters and XNAME is a customer's canonical name (e.g., "Doe, Johnny"). The application schema has one cross reference index, ^XALPHA("A",XNAME,ACN)="" .  A GT.M trigger specified for ^CIF(:,1) nodes can automatically maintain the cross references.     
 
  1. Using your editor, create a trigger definition file called triggers.trg1with the following entry:
    +^CIF(acn=:,1) -delim="|" -pieces=2 -commands=SET,KILL -xecute="Do ^XNAMEinCIF"
    In this definition:
    ^CIF - specifies the global variable to which the trigger applies.
    acn=: - in ZWRITE syntax, ":" specifies any value for the first subscript, and the acn= prefix requests GT.M assign the value of the first subscript (ACN) to the local variable acn before invoking the trigger logic.
    1 - specifies that the trigger matches only if the second subscript is 1 (one).
    -delim="|" - specifies that GT.M use "|"  as the piece separator when checking the value of the node to see whether to invoke the trigger.  Use of the keyword delim tells GT.M to use $PIECE() semantics for the value at the node; zdelim, instead, would instruct GT.M to use $ZPIECE() semantics.
    -pieces=2 - specifies that GT.M should only invoke the trigger when the update changes the second piece (XNAME) not for a change to the first piece (NAM), or any other piece without a change to XNAME.
    -commands=SET,KILL - specifies that GT.M invoke the trigger for SET and KILL updates (but not a ZKILL/ZWITHDRAW command).
    -xecute="Do ^XNAMEinCIF" - provides code for GT.M to invoke to perform the trigger logic.

  2. 次のようなコマンドを実行します:
    $ mupip trigger -triggerfile=triggers.trg
    このコマンドは ^CIF(:,1) にトリガを追加します。
    トリガのロードが成功して、このコマンドは、次のような出力が表示されます:
    File triggers.trg, Line 1: ^CIF trigger added with index 1
    =========================================
    1 triggers added
    0 triggers deleted
    0 trigger file entries not changed
    0 triggers modified
    =========================================
    Now, every S[et] and K[ill] operation on the global node ^CIF(:,1) executes the routine XNAMEinCIF.

  3. エディタを使用して、次のコードで XNAMEinCIF.m をコールするMルーチンを作成します。 
    XNAMEinCIF ; Triggered Update for XNAME change in ^CIF(:,1)
        Set oldxname=$Piece($ZTOLDval,"|",2) Set:'$Length(oldxname) oldxname=$ZChar(254)    ; old XNAME 
        Kill ^XALPHA("A",oldxname,acn)                                                      ; remove any old xref 
        ; コマンドがSetされているなら、新しいクロスリファレンスを作成
        Do:$ZTRIggerop="S" 
        . Set xname=$Piece($ZTVALue,"|",2) Set:'$Length(xname) xname=$ZChar(254)            ; new XNAME
        . Set^XALPHA("A",xname,acn)=""                                                      ; create new xref
    ;
    When the XNAME piece of a ^CIF(:,1) node is SET to a new value or KILLed, we delete the existing cross references.  The deletion can be unconditional, because if the node did not previously exist, then the KILL is a no-op.  If the command is a SET, we create new cross references.  From the definition of the schema, the code uses the following values:
 
値を取得した後に、無条件のKILLコマンドは、クロスリファレンスのインデックスが存在する場合、以前のクロスリファレンスのインデックスを削除します。 Then, only if a SET invoked the trigger (determined from the ISV $ZTRIGGEROP), the trigger invoked routine creates a new cross reference index node. GT.Mは、トリガロジックによって新しいコンテキストを暗黙的に作成するため、名前または明示的な変数のNEWの選択を心配する必要はないことに注意してください。


The following illustration shows the flow of control when the trigger is executed for Set ^CIN(ACN,1)="Paul|John, Doe, Johnny|". The initial value of ^CIN(ACN,1) is "Paul|Doe, John|" and ACN is set to "NY".  


 
Important: Within trigger context (Step 1 through 4) , if you modify the value of $ZTVAL, GT.M commits it to the database at Step 5. GT.Mは、原子性(Atomic)(全か無か)はトランザクション単位として、すべてのステップ(0〜5)を実行します。

The following illustration shows the flow of control when the trigger is executed for Kill ^CIN(ACN,1).

トリガ定義の保存

GT.M stores trigger definitions as nodes of a global-like structure (^#t) within the same database as the nodes with which they're associated. You can manage the trigger definitions with MUPIP TRIGGER and $ZTRIGGER() but you cannot directly access ^#t (except with DSE, which FIS recommends against under normal circumstances). データベースのブロックサイズ、キーサイズ、レコードサイズは、関連付けられたトリガ定義を保持するのに十分なおおきさがなければなりません。加えて、更新トリガを使用するグローバルディレクトリのデフォルトの領域は、そのトリガ関連データを保持するために十分な、ブロックサイズ、キーサイズ、レコードサイズを持つ必要があるので、GT.Mは、デフォルト領域内の情報を解決するクロスリージョンの名を格納します。

トリガ呼出と実行のセマンティクス

GT.Mは、そのグローバル変数のためのデータベースファイル内の各グローバル変数のためにトリガを保存します。 When a global directory maps a global variable to its database file, it also maps triggers for that global variable to the same database file.  When an extended reference uses a different global directory to map a global variable to a database file, that global directory also maps triggers for that global variable to that same database file.


Although triggers for Set and Kill / ZKill commands can be specified together, the command invoking a trigger is always unique. The ISV $ZTRIggerop provides the trigger code which matched the triggering command.


コマンドがグローバル変数を更新するたびに、GT.Mランタイムシステムは、最初にそのグローバル変数にトリガがあるかどうかを決定します。 If there are any triggers, it scans the signatures for subscripts and node values to identify matching triggers.  If multiple triggers match, GT.M invokes them in an arbitrary order.  Since a future version of GT.M, potentially multi-threaded, may well choose to execute multiple triggers in parallel, you should ensure that when a node has multiple triggers, they are coded so that correct application behavior does not rely on the order in which they execute.


When a process executes a Kill, Zkill or Set command, the target is the global variable node specified by the command argument for modification.  With Set and ZKill, the target is a single node.  In the case of Kill, the target may represent an entire sub-tree of nodes.  GT.M only matches the trigger against the target node, and only invokes the trigger once for each Kill command.  GT.M does not check nodes in sub-trees to see whether they have matching triggers.

Kill / ZKill

If Kill or ZKill updates a global node matching a trigger definition, GT.M executes the trigger code when a database state change has been computed but before it has been applied in the process space or the database. KILLされるべきノードと(もしあれば)下位ノードがトリガコードに表示されたままになることを意味します。KILLトリガーが$ZTVALUEを無視することに注意してください。

Set

If a SET updates a global node matching a trigger definition, GT.M executes the trigger code after the node has been updated in the process address space, but before it is applied to the database.  When the trigger execution completes, the trigger logic commits the value of a node from the process address space only if $ZTVALUE is not set. if $ZTVALUE is set during trigger execution, the trigger logic commits the value of a node from the value of $ZTVALUE

次の例を考えてみます。


GTM>set c=$ztrigger("S")

;trigger name: A#1#  cycle: 1

+^A -commands=S -xecute="set ^B=200"

;trigger name: B#1#  cycle: 1

+^B -commands=S -xecute="set $ztval=$ztval+1 "

 

GTM>set ^A=100,^B=100

 

GTM>write ^A

100

GTM>write ^B

201


SET ^A=100 invokes trigger A#1. When the trigger execution begins, GT.M sets ^A to 100 in the process address space, but does not apply it to the database. Therefore, the trigger logic sees ^A as set to 100. Other process accessing the database, however, see the prior value of ^A.

When the trigger execution completes, the trigger logic commits the value of a node from the process address space only if $ZTVALUE is not set. The trigger logic commits the value of a node from the $ZTVALUE only if $ZTVALUE is set during trigger execution. 

Because $ZTVALUE is not set in A#1, GT.M commits the value of ^A from the process address space to the database. Therefore, GT.M commits ^A=100 to the database.

SET ^B=200 invokes trigger B#2. $ZTVALUE is set during trigger execution, therefore GT.M commits the value of $ZTVALUE to ^B at the end of trigger execution.

Note: Within trigger code, any SET operation on ^B recursively invokes trigger B#1. Therefore, always set $ZTVALUE to change the value node during trigger execution.

GT.M executes the triggering update and all associated triggers within the same transaction, whether or not the original command is inside a transaction.  This means that although the trigger logic sees the updated value of the node, it is not visible to other processes until the outermost transaction commits to the database.


トリガは、開始トリガをSETするノードを更新する必要があります。 Situations where this may occur include:


そのような場合には、トリガのロジックは、グローバル ノードの代わりに ISV $ZTVALUEに変更を加える必要があります。 At the end of the trigger invocation, GT.M applies the value in $ZTVALUE to the node. Before the first matching trigger executes, GT.M sets $ZTVALUE.  Since a command inside one trigger's logic can invoke another nested trigger, if already in a trigger, GT.M stacks the value of $ZTVALUE for the prior update before modifying it for the nested trigger initiation.


GT.Mは、データソースの照合順序で実行されるSETコマンドのシリーズとしてMERGEコマンドを扱います。 GT.M checks each global node updated by the MERGE for matching triggers.  If GT.M finds one or more matches, it invokes all the matching trigger(s) before the next command or the next set argument to the same SET command.


GT.Mは、SETコマンドとして$INCREMENT() 関数を扱います。 Since the result of a $INCREMENT() operation must be numeric, if the trigger code modifies $ZTVALUE, at the end of the trigger, GT.M applies the value of +$ZTVALUE (that is, $ZTVALUE coerced to a number) to the target node.


トリガの実行環境

上述したように、もし複数のマッチングのトリガがある場合は、GT.Mプロセスは、マッチングのトリガのリストを作り、そして、予測可能性の保証なしで任意の順序でそれらを実行します。

 

各マッチングトリガ:


  1. GT.Mプロセスは、ネイキッド リファレンス、$REFERENCE、$TEST、ZTOLDVAL、$ZTDATA、ZTRIGGEROP、$ZTUPDATEと、すべてのローカル変数のNEWなどを、暗黙的にスタックします。At the beginning of trigger code execution, $REFERENCE, $TEST and the naked indicator initially retain the values they had just prior to being stacked (in the case of KILL/ZKILL, to the reference of the KILL/ZKILL command, even though the trigger executes prior to the removal of any nodes).  If an update directly initiates multiple (chained) triggers, all start with identical values of the naked reference, $REFERENCE, $TEST, $ZTDATA, $ZTLevel, $ZTOLDVAL and $ZTRIGGEROP.  This facilitates triggers that are independent of the order in which they run.  Application logic inside triggers can use $REFERENCE, the read-only intrinsic special variables $ZTDATA, $ZTLEVEL, $ZTOLDVAL, $ZTRIGGEROP & $ZTUPDATE, and the read-write intrinsic special variables $ZTVALUE, and $ZTWORMHOLE.
  2. GT.Mは、トリガのコードを実行します。Note that in the course of executing this GT.M trigger, if the same trigger matches again for the same or a different target, GT.M reinvokes the trigger recursively.  In other words, the same trigger can be invoked more than once for the same command.  Note that such a recursive invocation is probably a pathological condition that will eventually cause a STACKCRIT error. トリガはの最大127レベルまでネストし、その後は、ネストへ追加する試みは、MAXTRGRNESTエラーを生成します。
  3. コードが完了すると、GT.Mは、ローカル変数をクリアし、$ZTVALUEを除いて ($ZTVALUEの変更でのコメントについてはISVの定義を参照)、それらがトリガの開始時にあった値にスタックしたものをレストアし、そして、オリジナルの更新にマッチングする残りのトリガのいずれかが存在する場合、$ZTUPDATEを調整し、その次のアクションを実行します。$ZTVALUEは、アプリケーションのアップデートが最初にトリガを起動しているノードの現在のターゲット値を、常に保持します。同じノードの複数のトリガは任意の順序で実行するので、$ZTVALUEを変更する1つ以上のトリガを持つには、設計と実装には注意を必要とすることに注意してください。


すべてのトリガを実行した後、GT.Mは、トリガアップデートだけでなくトリガ開始の操作をコミットし、そして、次のコマンドで実行を継続します(または、次のノードで、同じコマンドによって更新されている複数のノードの場合)。 Note that if the operation initiating the trigger is itself within a transaction, other processes will not see the database state changes till the TCOMMIT of the outermost transaction.


トリガアクションがそれらを呼び出す更新に関してアトミックであることを確認するために、GT.Mは、トリガロジックとのトランザクション内でトリガアップデートを常に実行します。 If the triggering update is not within an application transaction, GT.M implicitly starts a restartable "Batch" transaction to wrap the original update and any triggers generated by the update.  In other words, when 0=$TLEVEL GT.M behaves as if implicit TStart *:Transactionid="BATCH" and TCommit commands bracket the upddate and its triggers. したがって、トリガコードおよび/またはそのエラートラップは、トランザクション内で常に動作し、もしメインアプリケーションコードがTSTARTを使用していない場合でも、TRESTARTコマンドを使用することができます。トリガで使用するための$ETRAPコードは、TROLLBACKロジックを含めることができます。


推奨されていないZTSTART / ZTCOMMITトランザクションは、トリガと互換性がありません。 If a ZTSTART transaction is already active when an update to a global that has any trigger defined occurs, GT.M issues a runtime error. 同様に、GT.Mは、エラーとしてトリガ コンテキスト内でZTSTARTを発行しようとする試みを扱います。

トリガ実行中のエラー処理

GT.Mは、トリガの実行中にエラーを処理する$ETRAPメカニズムを使用します。もしトリガ中にエラーが発生した場合、GT.Mは、$ETRAPのMコードを実行します。もし$ETRAPが$ECODEをクリアしない場合は、GT.Mは、トリガ内のデータベース更新をコミットせず、トリガアップデートの環境に制御を渡しません。もし$ETRAPアクションまたはそれが呼び出すロジックが$ECODEをクリアすると、GT.Mはトリガ ロジックの処理を続行することができます。


以下のささいな例を考えてみましょう:

^Acct(id=:,disc=:) –commands=Set –xecute="Set msg=""Trigger Failed"",$ETrap=""If $Increment(^count) Write msg,!"" Set $ZTVAlue=x/disc"


During trigger execution if disc (the second subscript of the triggering update) evaluates to zero, resulting in a DIVZERO (Attempt to divide by zero) error, GT.M displays the message "Trigger Failed".  Since the $ETRAP does not clear $ECODE, after printing the message, GT.M leaves the trigger context and invokes the error handler outside the trigger, if any.  In a DIVZERO case, the process neither assigns a new value to ^Acct(id,disc) nor commits the incremented value of ^count to the database.


アプリケーション プロセスは、トリガ内でランタイムエラーを処理するために、補正処理の広い範囲を使用できます。しかし、これらの補正処理は、MUPIPレプリケーション中に、使用できない場合があります。トリガ環境のセクションで説明したように、GT.Mは、トリガ定義だけをレプリケートしますが、しかし、レプリケーションインスタンスがそれらをリプレイする時、トリガーによって実行されるそのトリガアップデートはレプリケートしません。もしトリガがレプリケーションインスタンスで呼び出された場合には、トリガが正常にオリジナルのインスタンスで呼び出されたことを意味します。 For normal application requirements, you should ensure that the trigger produces the same results on a correctly configured replicating instance. したがって、MUPIP上の$ETRAPコードは、次のような場合に対処する必要があります:
 

 

この後の2つの事例で、ミスマッチ環境のために、基本的な2つの可能性がおそらくあります - それらは、次のとおりです:
 
 

トリガ機能はgtm_trigger_etrapと呼ばれる環境変数を導入しています。トリガのコンテキストで$ETRAPの初期値を提供し、mumpsとMUPIPプロセスの両方でトリガ操作用のエラートラップをセットするために使用できます。コードは、もちろん、トリガのコンテキスト内でSET $ETRAPもできます。もし gtm_trigger_etrap とトリガの失敗の値を指定しない場合、ランタイム トリガの動作時には、GT.Mは、現在のトラップハンドラを使用します。mumpsプロセスでは、もしトラップハンドラがトリガアップデートの時点で$ZTRAPがあった場合とgtm_trigger_etrap が定義されていない場合に、$ZTRAPがアンスタックでかつ有効になる前に、エラートラップは、トリガ ロジックとトリガアクションの両方の外側で終了する$ETRAP="" に暗黙的に置換されます。MUPIPプロセスでは、もしgtm_trigger_etrapとリガの失敗の値を指定しない場合、GT.Mは SET $ETRAP="If $ZJOBEXAM()" を、暗黙的に実行し、MUPIPプロセスを終了します。$ZOBEXAM()は、失敗の解析のための基礎を提供するファイルに診断情報(ZSHOW "*" に相当)を記録します。

 

重要:$ZJOBEXAM() は、関数の実行時にプロセスのコンテキストをダンプし、そして、出力は識別番号、クレジットカード番号などのような機密情報も含むことができます。MUPIPエラーハンドラによって生成されたファイルの場所をセキュアにすべきか、または、MUPIP操作のために適切なセキュリティ特性を設定する必要があります。代わりに、もし、$ZJOBEXAM() ファイルを作成するMUPIPを必要としない場合は、"Write !,$ZSTATUS,!,$ZPOSITION,! Halt" のようなハンドラを gtm_trigger_etrap 環境変数に明示的にセットします。Halt".

 

トリガーの実行中のエラー処理の他の重要な側面は次のとおりです: 
 
$

ZGOTO

トリガのトランザクション整合性を維持するために、そして、不適切な最終点に制御を分岐を避けるために、ZGOTOは次のように動作します:

 
  1. それらはMUPIPコンテキストを置換する試みを形成するので、GT.Mは、MUPIPの ZGOTO 1:<entryref> 引数をサポートしません。 
  2. ZGOTO引数が、トリガを開始したアップデートのレベル以下の entryref を指定した場合、GT.Mは、トリガ更新を実行せずに entryref に制御フローをリダイレクトします。GT.Mはnull 以外の$ECODEを見つける代わりに、それがトリガを完了することになる時に未処理のエラーを示し、オリジナルのトリガ更新をコミットするのではなく、現在のエラーハンドラへ制御を投げますします。
  3. ZGOTO 0 はプロセスを終了して、トリガの呼び出しの外側である必要がありますベースのスタックフレームへのZGOTO 1を返します。 更新が発生したレベルがないentryrefを引数に指定してZGOTOは、更新自体に返すため、ランタイム·トリガのコンテキスト内からZGOTOは、直接(ように、トリガを起動したコマンドを含む行に、後続のMコマンドに到達することはできません$ ECODEがNULLの場合は、GT.Mは、任意の追加のトリガと行を再開する前にトリガ更新を処理を続行し、QUIT)となります。
  4. ZGOTO from within a run-time trigger context cannot directly reach a subsequent M command on the line containing the command that invoked the trigger, because a ZGOTO with an argument specifying the level where the update originated but no entryref returns to the update itself (as would a QUIT) and, if $ECODE is null, GT.M continues processing with any additional triggers and the triggering update before resuming the line.

GT.CM

GT.CM servers do not invoke triggers. This means that the client processes must restrict themselves to updates which don't require triggers, or explicitly call for the actions that triggers would otherwise perform. Because GT.CM bypasses triggers, it may provide a mechanism to bypass triggers for debugging or complex corrections to repair data placed in an inconsistent state by a bug in trigger logic.

その他のユーティリティ

During MUPIP INTEG, REORG and BACKUP (including -BYTESTREAM), GT.M treats trigger definitions just as it treats any normal global node. 

 

Because they are designed as state capture and [re]establishment facilities, MUPIP EXTRACT does not extract trigger definitions and MUPIP LOAD doesn't restore trigger definitions or invoke any triggers. While you can construct input for MUPIP LOAD which bypasses triggers, there is no way for M code itself to bypass an existing trigger, except by using a GT.CM configuration. The $ZTRIGGER() function permits M code to adjust the triggers, including removing triggers, but those actions affect all processes updating the node associated with any trigger. Like MUPIP EXTRACT and LOAD, the ^%GI and ^%GO M utility programs do not extract and load GT.M trigger definitions. Unlike MUPIP LOAD, ^%GI invokes triggers just like any other M code, which may yield results other than those expected or intended.

ジャーナリングとデータベースのレプリケーションのトリガー  

GT.M handles "trigger definitions" and "triggered updates" differently.


ジャーナリング

Effective V5.4-000, the journal extract format changed to accomodate triggers. You may need to adjust the code which reads and processes journal extracts. Here is the summary of the journal extract format changes in V5.4-000:
 

Prior to V5.4-000

V5.4-000 onwards

Journal extract format GDSJEX03 (UNIX)
GDSJEX01 (VMS)
GDSJEX04

Existing journal record types

KILL

04\time\tnum\pid\clntpid\token_seq\node

04\time\tnum\pid\clntpid\token_seq\updnum\nodeflags\node

SET

05\time\tnum\pid\clntpid\token_seq\node=sarg

05\time\tnum\pid\clntpid\token_seq\updnum\nodeflags\node=sarg

ZTSTART

06\time\tnum\pid\clntpid\token\jsnum

06\time\tnum\pid\clntpid\token

ZTCOM

07\time\tnum\pid\clntpid\token\jsnum\partners

07\time\tnum\pid\clntpid\token\partners

ZKILL

10\time\tnum\pid\clntpid\token_seq\node

10\time\tnum\pid\clntpid\token_seq\updnum\nodeflags\node

NULL

NULL records are only possible when you use replication and external M-filters. Journal files generated by GT.M do not have NULL records.
New journal record types

ZTWORM

---NA---

11\time\tnum\pid\clntpid\token_seq\ztwormhole

 

Legend (additions and changes):

nodeflags: Decimal number interpreted as a binary mask. Currently only 4 bits are used.
    0001 (1) => update journaled but NOT replicated (For example, update inside a trigger)
    0010 (2) => update to a global that had at least one trigger defined, even if no trigger matched this update
    0100 (4) => $ZTWORMHOLE holds the empty string ("") at the time of this update or was not referenced during this update
    1000 (8) => update did not invoke any triggers even if they existed (For example, MUPIP LOAD) 
    Combinations of the above bits would mean each of the individual bit characteristics.
    For example,  0011 => update within a trigger context, and to a global with at least one trigger defined. Certain bit combinations are impossible. For example, 1001 since GT.M replicates any update that does not invoke triggers.
partners:
Number of journaled regions participating in this TP or ZTP transaction (TCOM/ZTCOM record written in this TP or ZTP)
ztwormhole:
string value from/for $ZTWORMHOLE. 

When journaling is ON, GT.M generates journal records for database updates performed by trigger logic. For an explicit database update, a journal record specifies whether any triggers were invoked as part of that update. GT.M triggers have no effect on the generation and use of before image journal records, and the backward phase of rollback / recovery.

A trigger associated with a global in a region that is journaled can perform updates in a region that is not journaled. However, if triggers in multiple regions update the same node in an unjournaled region concurrently, the replay order for recovery or rollback might differ from that of the original update and therefore produce a different result; therefore this practice requires careful analysis and implementation. Except when using triggers for debugging, FIS recommends journaling any region that uses triggers.

 

The following sample journal extract shows how GT.M journals records updates to trigger definitions and information on $ZWORmhole:

 

GDSJEX04
01\61731,15123\1\16422\gtm.node1\gtmuser1\21\0\\\
02\61731,15123\1\16422\0
01\61731,15126\1\16423\gtm.node1\gtmuser1\21\0\\\
08\61731,15126\1\16423\0\4294967297
05\61731,15126\1\16423\0\4294967297\1\4\^#t("trigvn","#LABEL")="1"
05\61731,15126\1\16423\0\4294967297\2\4\^#t("trigvn","#CYCLE")="1"
05\61731,15126\1\16423\0\4294967297\3\4\^#t("trigvn","#COUNT")="1"
05\61731,15126\1\16423\0\4294967297\4\4\^#t("trigvn",1,"TRIGNAME")="trigvn#1#"05\61731,15126\1\16423\0\4294967297\5\4\^#t("trigvn",1,"CMD")="S"
05\61731,15126\1\16423\0\4294967297\6\4\^#t("trigvn",1,"XECUTE")="W $ZTWORMHOLE s ^trigvn(1)=""Triggered Update"" if $ZTVALUE=1 s $ZTWORMHOLE=$ZTWORMHOLE_"" Code:CR"""
05\61731,15126\1\16423\0\4294967297\7\4\^#t("trigvn",1,"CHSET")="M"
05\61731,15126\1\16423\0\4294967297\8\4\^#t("#TRHASH",175233586,1)="trigvn"_$C(0,0,0,0,0)_"W $ZTWORMHOLE s ^trigvn(1)=""Triggered Update"" if $ZTVALUE=1 s $ZTWORMHOLE=$ZTWORMHOLE_"" Code:CR""1"
05\61731,15126\1\16423\0\4294967297\9\4\^#t("#TRHASH",107385314,1)="trigvn"_$C(0,0)_"W $ZTWORMHOLE s ^trigvn(1)=""Triggered Update"" if $ZTVALUE=1 s $ZTWORMHOLE=$ZTWORMHOLE_"" Code:CR""1"
09\61731,15126\1\16423\0\4294967297\1\1\
02\61731,15127\2\16423\0
01\61731,15224\2\16429\gtm.node1\gtmuser1\21\0\\\
08\61731,15224\2\16429\0\8589934593
11\61731,15224\2\16429\0\8589934593\1\"A process context like--> Discount:10%;Country:IN"
05\61731,15224\2\16429\0\8589934593\1\1\^trigvn="Initial Update"
09\61731,15224\2\16429\0\8589934593\1\1\BA
08\61731,15232\3\16429\0\12884901889
11\61731,15232\3\16429\0\12884901889\1\"A process context like--> Discount:10%;Country:IN Code:CR"
05\61731,15232\3\16429\0\12884901889\1\1\^trigvn="1"
09\61731,15232\3\16429\0\12884901889\1\1\BA
08\61731,15260\4\16429\0\17179869185
11\61731,15260\4\16429\0\17179869185\1\"A process context like--> Discount:10%;Country:IN Code:CR"
05\61731,15260\4\16429\0\17179869185\1\1\^trigvn="Another Update"
09\61731,15260\4\16429\0\17179869185\1\1\BA
02\61731,15263\5\16429\0
01\61731,15865\5\26697\gtm.node1\gtmuser1\21\0\\\
08\61731,15865\5\26697\0\21474836481
05\61731,15865\5\26697\0\21474836481\1\2\^trigvn(1)="Updated outside the trigger."
09\61731,15865\5\26697\0\21474836481\1\1\BA
02\61731,15870\6\26697\0
01\61731,15886\6\26769\gtm.node1\gtmuser1\21\0\\\
08\61731,15886\6\26769\0\25769803777
11\61731,15886\6\26769\0\25769803777\1\" Code:CR"
05\61731,15886\6\26769\0\25769803777\1\1\^trigvn="1"
09\61731,15886\6\26769\0\25769803777\1\1\BA
02\61731,15895\7\26769\0
01\61731,15944\7\26940\gtm.node1\gtmuser1\21\0\\\
08\61731,15944\7\26940\0\30064771073
05\61731,15944\7\26940\0\30064771073\1\3\^trigvn="Another Update"
09\61731,15944\7\26940\0\30064771073\1\1\BA
08\61731,16141\8\26940\0\34359738369
11\61731,16141\8\26940\0\34359738369\1\"A process context like--> Discount:10%;Country:IN  Code:CR"
05\61731,16141\8\26940\0\34359738369\1\1\^trigvn="1"
09\61731,16141\8\26940\0\34359738369\1\1\BA
08\61731,16178\9\26940\0\38654705665
11\61731,16178\9\26940\0\38654705665\1\"A process context like--> Discount:10%;Country:IN  Code:CR"
05\61731,16178\9\26940\0\38654705665\1\1\^trigvn="Another update"
09\61731,16178\9\26940\0\38654705665\1\1\BA
02\61731,16210\10\26940\0
01\61731,16517\10\5337\gtm.node1\gtmuser1\21\0\\\
08\61731,16517\10\5337\0\42949672961
05\61731,16517\10\5337\0\42949672961\1\2\^trigvn(1)="4567"
09\61731,16517\10\5337\0\42949672961\1\1\BA
08\61731,16522\11\5337\0\47244640257
11\61731,16522\11\5337\0\47244640257\1\" Code:CR"
05\61731,16522\11\5337\0\47244640257\1\1\^trigvn="1"
09\61731,16522\11\5337\0\47244640257\1\1\BA
08\61731,16544\12\5337\0\51539607553
11\61731,16544\12\5337\0\51539607553\1\"No context Code:CR"
05\61731,16544\12\5337\0\51539607553\1\1\^trigvn="1"
09\61731,16544\12\5337\0\51539607553\1\1\BA
02\61731,16555\13\5337\0
03\61731,16555\13\5337\0\0
 

This journal extract output shows $ZTWORMHOLE information for each triggered update to ^trigvn. Notice how GT.M stored trigger definitions as a node of a global-like structure ^#t and how GT.M journals the trigger definition for ^trigvn and the triggered update for ^trgvn.


Note: GT.M implicitly wraps a trigger as an M transaction. Therefore, a journal extract file for a database that uses triggers has Type 8 and 9 (TSTART/TCOMMIT) records even if the triggers perform no updates (that is, are effectively No-ops).

MUPIP JOURNAL -RECOVER / -ROLLBACK

The lost and broken transaction files generated by MUPIP JOURNAL -RECOVER / -ROLLBACK contain trigger definition information. You can identify these entries + or - and appropriately deal with them using MUPIP TRIGGER and $ZTRIGGER().    

マルチサイトのデータベース レプリケーション

During replication, GT.M replicates trigger definitions to ensure that when MUPIP TRIGGER updates triggers on an initiating instance, all replicating instances remain logically identical.

 

The replication stream has no records for updates generated by implicit GT.M trigger logic. If your trigger action invokes a routine, specify the value of the gtmroutines environment variable before invoking replication with MUPIP so the update process can locate any routines invoked as part of trigger actions. 

 

To support upward compatibility, V5.4-000 allows your originating primary to replicate to:

 

 

When a replicating instance needs to serve as a possible future originating instance, you must carefully design your replication filters to handle missing triggers or trigger mismatch situations to maintain logical consistency with the originating primary.

インスタンスに別のトリガ設定でレプリケート

During an event such as rolling upgrade, the replicating instance may have a new database schema (due to application upgrades) and in turn a new set of triggers.  Therefore, GT.M replication allows you to have different-trigger configuration for originating (primary) and replicating (secondary) instances.  When replication starts between the two instances, any update to triggers on the originating instance automatically flow (through the filters) to the replicating instance. For the duration of the rolling upgrade, your application must use replication filters to ensure trigger updates on the originating instance produce an appropriate action on the replicating instance.  However, whenever you follow the practice of creating replicating instances from backups of other appropriate originating instances, you do not have to use additional replication filters, because the backups include GT.M trigger definitions, under normal conditions instances automatically have the same triggers.

 

Because the replication stream carries the native key format, having different collation for a replicated global on the replicating node from that on the initiating node is effectively a schema change and requires an appropriate filter to appropriately transform the subscripts from initiating form to replicating form. This is true even without triggers. However, with triggers a mismatch also potentially impacts appropriate trigger invocation.

 

Because GT.M stores triggers in the database files as pseudo global variables, an application upgrade requiring a change to triggers is, in the worst case, no different than an application upgrade that changes the database schema, and can be handled under current rolling upgrade methods. Some changes to GT.M triggers may well be much simpler than a database schema change, and may not need a rolling upgrade. 

サポートしていないインスタンスにレプリケートトリガー

At replication connection, if an originating primary detects a replicating instance that does not support triggers, the Source Server issues a warning to the operator log and the Source Server log. The Source Server also sends a warning message to the operator log and the Source Server log the first time it has to replicate an update associated with a trigger. In this configuration, internal filters in GT.M strip the replication stream of trigger-related information such as $ZTWORMHOLE data and trigger definition updates from MUPIP TRIGGER or $ZTRIGGER(). The Source Server does send updates done within trigger logic.  Unless the application has replication filters that appropriately compensate for the trigger mismatch, this is a situation for concern, as the replicating instance may not maintain logical consistency with the originating primary. Note that filters that deal with $ZTWORMHOLE issues must reside on the originating instance.   

アップデートとヘルパープロセス

For any replication stream record indicating triggers were invoked, the Update Process scans for matching GT.M triggers and unconditionally executes the implicit GT.M trigger logic.

MUPIP TRIGGER and $ZTRIGGER()

MUPIP TRIGGER provides a facility to examine and update triggers. The $ZTRIGGER() function performs trigger maintenance actions analogous to those performed by MUPIP TRIGGER. $ZTRIGGER() returns the truth value expression depending on the success of the specified action. You choice of MUPIP TRIGGER or $ZTRIGGER() for trigger maintenance should depend on your current application development model and configuration management practices.   Both MUPIP TRIGGER and $ZTRIGGER() use the same trigger definition syntax. You should familiarize yourself with the syntax of an entry in a trigger definition file before exploring MUPIP TRIGGER and $ZTRIGGER().  

MUPIP トリガ

Examines or loads trigger definitions. The format of the MUPIP TRIGGER command is:

 

MUPIP TRIGGER {-TRIG[gerfile]=<trigger_definitions_file>[ -NOPR[ompt]]| [-SELE[ct][=name-list|*][ <select-output-file>]}

 

Before you run the MUPIP TRIGGER command:


The qualifiers of the MUPIP TRIGGER command are as follows:

TRIGgerfile

Loads a trigger definition file to the database. The format of the TRIGGERFILE qualifier is:

 

-TRIG[gerfile]=<trigger_definitions_file>[-noprompt]

Note: The trigger update  summary reports count not only names and option changes as "modified" but also cases where a -COMMANDS list changed, even though those are functionally additions or deletions of separate trigger definitions.

SELEct

Provides a facility to examine the current trigger definition. SELECT produces a list of the current triggers for a comma-separate list of global variables or trigger names. The format of the SELECT qualifier is:

 

-SELE[ct][=name-list[*]|*][ <select-output-file>]  
 

 

Note: The output from the MUPIP TRIGGER –SELECT command may not be identical to your trigger definition file. This is because GT.M converts some semantically identical syntax into a single internal representation; while -SELECT output may not be identical to the -TRIGGERFILE input, it has the same meaning.  Additionally, MUPIP TRIGGER -SELECT displays a field called "Cycle" as part of a comment. Cycle is the number of trigger definition updates (addition, modification, or deletion) performed on a global.

 

MUPIPトリガーの例

This section provides step-by-step instructions for creating, modifying, and deleting triggers. Triggers affect all processes updating a database unlike, for example, environment variables such as $gtmroutines which work on a per process basis. Therefore, FIS recommends that you should always have carefully planned procedures for changing triggers in your production environment.  

 

To create a new trigger for global node ^Acct("ID"):  

  1. Using your editor, create a trigger definition file called triggers.trg with the following entry: 
    +^Acct("ID") -name=ValidateAccount -commands=S -xecute="Write ""Hello Earth!"""

  2. 次のようなコマンドを実行します:
    $ mupip trigger –triggerfile=triggers.trg
    This command adds a trigger for ^Acct("ID"). トリガのロードが成功して、このコマンドは、次のような出力が表示されます:
    File triggers.trg, Line 1: ^Acct trigger added with index 1
    =========================================
    1 triggers added
    0 triggers deleted
    0 trigger file entries not changed
    0 triggers modified
    =========================================
    Now, every S[et] operation on the global node ^Acct("ID") executes the trigger.

  3. 次のようなコマンドを実行します:
    $ mupip trigger –select="^Acct*"
    This command displays the triggers. A sample output looks like the following: 
    ;trigger name: ValidateAccount#  cycle: 1
    +^Acct("ID") -name=ValidateAccount -commands=S -xecute="Write ""Hello Earth!"""
 
To modify an existing trigger for global node ^Acct("ID"):  

You cannot directly replace an existing trigger definition with a new one. With the exception of -NAME and -OPTIONS, to change an existing trigger, you have to delete the existing trigger definition and then add the modified trigger definition as a new trigger. Note that GT.M performs two different trigger comparisons to match trigger definitions depending on whether or not S[ET] is the trigger invocation command. If there is a S[ET], then the comparison is based on the global name and subscripts, PIECES, [Z]DELIM, and XECUTE. If there is no SET, GT.M compares only the global node with subscripts and the -XECUTE code value.

  1. Begin by executing the following command:
    $mupip trigger -select="^Acct*"
    Output file: 
  2. Specify trigger_mod.trg as the output file. This file contains entries like the following:
    ;trigger name: ValidateAccount#  cycle: 1
    +^Acct("ID") -name=ValidateAccount -commands=S -xecute="Write ""Hello Earth!"""
  3. Using your editor, open trigger_mod.trg and change + (plus) to - (minus) for the trigger definition entry for ValidateAccount and add a new trigger definition for ^Acct("ID"). To avoid inconsistent application behavior, it is important to replace an old trigger with a new one in the same transaction (Atomic). The trigger_mod.trg file should have entries like:
    ;trigger name:  ValidateAccount#    cycle: 1
    -^Acct("ID") -name=ValidateAccount -commands=Set -xecute="Write ""Hello Earth!"""
    ;trigger name: ValidateAccount#
    +^Acct("ID") -name=ValidateAccount -commands=Set -xecute="Write ""Hello Mars!""" 
  4. 次のようなコマンドを実行します:
    $ mupip trigger -triggerfile=trigger_mod.trg
    This command displays an output like the following:  
    File trigger_mod.trg, Line 1: ^Acct trigger deleted
    File trigger_mod.trg, Line 3: ^Acct trigger added with index 1
    =========================================
    1 triggers added
    1 triggers deleted
    0 trigger file entries not changed
    0 triggers modified
    =========================================

    おめでとう!You have successfully modified the xecute string of ValidateAccount with the new one. 
     
  To delete an existing trigger for global node ^Acct("ID"):     

  1. Begin by executing the following command: 
    $mupip trigger -select="^Acct*"
    Output file:

  2. Specify trigger_delete.trg as the output file. This file contains entries like the following:
    ;trigger name: ValidateAccount#  cycle: 3
    +^Acct("ID") -name=ValidateAccount -commands=S -xecute="Write ""Hello Mars!"""

  3. Using your editor, change + (plus) to - (minus) for the trigger definition entry for ValidateAccount. Alternatively, you can create a file with an entry like -ValidateAccount.  

  4. Now, execute a command like the following:
    $ mupip trigger -triggerfile=trigger_delete.trg

    This command displays an output like the following: 

        File trigger_delete.trg, Line 2: ^Acct trigger deleted
        =========================================
     0 triggers added
     1 triggers deleted
     0 trigger file entries not changed
     0 triggers modified
     =========================================

        

You have successfully deleted trigger "ValidateAccount".


To change a trigger name for global node ^Acct("ID"):  

  1. Using your editor, create a new file called trigger_rename.trg and add a trigger definition entry for ValidateAcct with the same trigger signature as ValidateAccount. Your trigger definition would look something like: 
    +^Acct("ID") -name=ValidateAcct -commands=S -xecute="Write ""Hello Mars!"""
  2. Verify that the ValidateAccount trigger exists by executing the following command:
    $mupip trigger -select="^Acct*"
    Output file:

  3. Respond with an empty string (Press Enter). Confirm that the trigger summary report contains an entry like the following:
    ;trigger name: ValidateAccount#  cycle: 3

    +^Acct("ID") -name=ValidateAccount -commands=S -xecute="Write ""Hello Mars!"""
  4. Now, execute a command like the following:
    $ mupip trigger -triggerfile=trigger_rename.trg

    This command displays an output like the following:
    =========================================
    0 triggers added
    0 triggers deleted
    0 trigger file entries not changed
    1 triggers modified
    =========================================
    You have successfully changed the trigger name ValidateAccount to ValidateAcct.

$ZTRIGGER

Use the $ZTRIGGER() function to examine or load trigger definition. The format of the $ZTRIGGER() function is:  
 
$ZTRIgger(expr1[,expr2])  
 

$ZTRIGGERの例は

GTM>set X=$ZTRIGGER("S")

This example displays the current trigger definitions stored in the database.

GTM>set X=$ZTRIGGER("i","+^Acct(sub=:) - command=Set -xecute=""Set ^X($ZTVALUE)=sub""")

This example adds a trigger definition for the first level node of ^Acct.

ISVs and Environment Variables 

GT.M provides seven ISVs (Intrinsic Special Variables) to facilitate trigger operations. With the exception of $ZWORMHOLE, all trigger-related ISVs return zero (0) if they have numeric values or an empty string when referenced by code outside of a trigger context.

$ZTCOde

Within trigger context, $ZTCOde evaluates to a string containing the trigger code (that is, the string value for the –xecute in the trigger definition). Outside trigger context, $ZTCOde has the value of an empty string.

 
例:

$ZTCode evaluates to Write "Hello Mars!" in the context of trigger in the following definition:

 
+^Acct("Id") -name=Acct -commands=Set -xecute="Write ""Hello Mars!"""

Note that even though the quotes inside the -xecute literal are doubled as in normal M, $ZTCode evaluates them as one quote, again as in normal M.

$ZTDAta

Within trigger context, $ZTDATA returns $Data(@$REFERENCE)#2 for a SET or $Data(@$REFERENCE) for a KILL, ZKILL or ZWITHDRAW prior to the explicit update. This provides a fast path alternative, avoiding the need for indirection in trigger code, to help trigger code determine the characteristics of the triggering node prior to the triggering update. For a SET, it shows whether the node did or did not hold data - whether a SET is modifying the contents of an existing node or creating data at a new node. For a KILL it shows whether the node had descendants and whether it had data.

 
Outside trigger context, $ZTDATA, returns zero (0).

$ZTLevel

Within trigger context, $ZTLevel returns the current level of trigger nesting (invocation by a trigger of an additional trigger by an update in trigger context).

 
$ZTLevel greater than one (>1) indicates that there are nested triggers in progress. When a single update invokes multiple triggers solely because of multiple trigger matches of that initial (non-trigger) update, they aren’t nested (they are chained) and thus all have same $ZTLevel.


Outside trigger context (no trigger active), $ZTLevel returns 0.

 
例:
+^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"

These trigger definitions show different values of $ZTLevel when two triggers are called recursively (and pathologically).

 
+^Acct("ID") –commands=Set –xecute="Set ^Acct(1)=$ZTVALUE+1"
+^Acct(sub=:) - command=Set -xecute="Set ^X($ZTVALUE)=sub"
 
SET ^Acct("ID")=10 invokes both the above triggers in some order and $ZTLevel will have the same value in both because these triggers are chained rather than nested.

$ZTOLdval

Within trigger context, $ZTOLDVAL returns the prior (old) value of the global node whose update caused the trigger invocation. This provides a fast path alternative to $Get(@$REFERENCE) at trigger entry (which avoids the heavyweight indirection ). If there are multiple triggers matching the same node (chained), $ZTOLDVAL returns the same result for each of them.
 

Outside trigger context, $ZTOLDVAL has the value of an empty string.

 
例:
+^Acct(1,"ID") -commands=Set -xecute="Write ""Is ^Acct(1,ID) previously defined? "",$ZTDATA Write "" Old value of ^Acct(1,ID)="",$ZTOLDVAL Set ^Acct(1,""Name"")=""<First Name> <Last Name>"" Write ""Current Value of ^Acct(I,ID)="",^Acct(1,""ID"")"
 
Suppose ^Acct(1,"ID") has a value of 4412. This trigger gets invoked with a SET command like the following:
 
GTM>write ^Acct(1,"ID")
4412
GTM>set ^Acct(1,"ID")=9891
Is ^Acct(1,ID) previously defined?1
Old value of ^Acct(1,"ID")=4412
Current value of ^Acct(1,"ID")=9891

$ZTRIggerop

Within trigger context, for SET (including MERGE and $Increment() operations), $ZTRIGGEROP has the value "S". For KILL, $ZTRIGGEROP has the value "K" For ZKILL or ZWITHDRAW, $ZTRIGGEROP has the value "ZK".   Outside trigger context, $ZTRIGGEROP has the value of an empty string.
 

$ZTSlate

$ZTSLATEは、最も外側のトランザクションに呼び出されたチェーンまたはネストのトリガで利用したい文字列を指定できます(TSTARTが0から1の$TLEVELを取る時)。You might use $ZTSLATE to accumulate transaction-related information, for example $ZTOLDVAL and $ZTVALUE,  available within trigger context for use in a subsequent trigger later in the same transaction. For example,  you can use $ZTSLATE to build up an application history or journal record to be written when a transaction is about to commit.

You can SET $ZTSLATE only while a database trigger is active. GT.M clears $ZTSLATE for the outermost transaction or on a TRESTART. However, GT.M retains $ZTSLATE for all sub-transactions (where $TLEVEL>1).


$ZTUPdate

Within trigger context, for SET commands where the GT.M trigger specifies a piece separator, $ZTUPDATE provides a comma separated list of piece numbers of pieces that differ between the current values of $ZTOLDVAL and $ZTVALUE. If the trigger specifies a piece separator, but does not specify any pieces of interest, $ZTUPDATE identifies all changed pieces.   $ZTUPDATE is 0 in all other cases (that is: for SET commands where the GT.M trigger does not specify a piece separator or for Kills). Note that if an update matches more than one trigger, all matching triggers see the same $ZTOLDVAL at trigger entry but potentially different values of $ZTVALUE so $ZTUPDATE could change due to the actions of each matching trigger even though all matching triggers have identical -[z]delim and -piece specifications.   Outside trigger context, $ZTUPDATE has the value of an empty string.  
 
例:

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

 
In the above trigger definition entry, $ZTUPDdate displays a comma separated list of the changed piece numbers if on of the pieces of interest: 1,3,4,5,or 6 are modified by the update.
 
GTM>write ^trigvn
Window|Table|Chair|Curtain|Cushion|Air Conditioner
GTM>set ^trigvn="Window|Dining Table|Chair|Vignette|Pillow|Air Conditioner"
4,5
 
Note that even though piece numbers 2,4 and 5 are changed, $ZTUPDATE displays only 4,5 because the trigger is not defined for updates for the second piece.

$ZTVAlue

For SET, $ZTVALUE has the value assigned to the node by the explicit SET operation. Modifying $ZTVALUE within a trigger modifies the eventual value GT.M assigns to the node. Note that changing $ZTVALUE has some performance impact as it causes an additional update operation on the node once all trigger code completes. If a node has multiple associated triggers each trigger receives the current value of $ZTVALUE, however, because the triggers run in arbitrary order, FIS strongly recommends no more than one trigger change any given element of application data, for example, a particular piece. For KILL and its variants, $ZTVALUE returns the empty string "". While GT.M accepts updates to $ZTVALUE within the trigger code invoked for a KILL or any of its variants, it ultimately discards any such value. Outside trigger context, $ZTVALUE has the value of an empty string and attempting to SET it produces a SETINTRIGONLY error.


$ZTWOrmhole

$ZTWORMHOLE allows you to specify a string up to 128KB of information you want to make available during trigger execution. You can use $ZTWORMHOLE to supply an application-context or process context to your trigger logic. Because GT.M makes $ZTWORMHOLE available throughout the duration of the process, you can access or update $ZTWORMHOLE both from inside and outside a trigger.
 
In many ways, $ZTWORMHOLE is like a wormhole (a popular concept in time-travel stories). Just as a wormhole provides a way to jump into a specific time-space continuum, $ZTWORMHOLE in GT.M provides a mechanism to access information from a process/application context that is otherwise unavailable in trigger context. GT.M records any non-empty string value of $ZTWORMHOLE in the GT.M database journal file as part of any update that invokes at least one trigger which references $ZTWORMHOLE. GT.M also transmits any non-NULL $ZTWORMHOLE value in the replication stream, thus providing the same context to triggers invoked by MUPIP processes (either as part of the replicating instance update process or as part of MUPIP journal recovery/rollback). Therefore, whenever you use $ZTWORMHOLE in a trigger, you create something like a wormhole for process context that is otherwise NEWed in the run-time or non-existent in MUPIP.
 
Note that if trigger code does not reference $ZTMOrmhole, GT.M does not make it available to MUPIP (via the journal files or replication stream). Therefore, if a replicating secondary has different trigger code than the initiating primary (an unusual configuration) and the triggers on the replicating node require information from $ZTWORMHOLE, the triggers on the intiating node must reference $ZTWORMHOLE to ensure GT.M maintains the data it contains for use by the update process on the replicating node. While you can change $ZWORmhole within trigger code, because of the arbitrary ordering of triggers on the same node, such an approach requires careful design and implementation.

GTM allows $ZTWOrmhole to be NEW’d. NEWing $ZTWOrmhole is slightly different from NEWing other ISVs/variables in the sense that the former retains its original value whereas the latter does not. However, like other NEWs, GT.M restores $ZTWOrmhole's value when the stack level pops.
 
The following example illustrates a simple use case for $ZTWORMHOLE.
 
Suppose a large commercial bank runs a real-time core processing application in about 4000 networked branches across US, Europe, and Asia. For each continent, one centrally-located GT.M database serves all instances of the real-time core processing application for each branch. To capitalize on market opportunities, the bank decides to offer 25% to 50% discount on buying a new investment product for its existing customers. The discount percentage is based on the applicable regulations and laws of the country served by the branch. Due to some recently introduced regulatory requirements in a country in Asia, a discount cannot be offered if the investment product is purchased by switching (that is, selling one investment product to buy another investment product).
 
This business rule can be implemented using the following guidelines:
 
 
Without $ZTWORmhole, additional update cycles and globals would have been consumed to preserve process-specific (applicable discount and switching) information.The following table summarizes the read/write permissions assigned to all trigger-related ISVs within trigger context and outside trigger context.
  
Intrinsic Special Variable
Outside Trigger Context    
Within Trigger Context
注意点
$ETrap
 Read / Write
 Read / Write
Set to gtm_trigger_etrap or the empty string when entering trigger context
$Reference
 Read only
 Read only
Restored at the completion of a trigger
$Test
 Read only
 Read only
Restored at the completion of a trigger
$TLevel
 Read only
 Read only
Always >=1 in trigger code; must be the same as the completion of processing a trigger as it was at the start
$ZTCOde
 Read only - ""
 Read only
Shows the trigger code
$ZTDAta
 Read only - 0
 Read only
Shows prior state
$ZTLEvel
 Read only - 0
 Read only
Shows trigger nesting
$ZTOLdval
 Read only - ""
 Read only
Shows the pre-update value
$ZTrap
 Read / Write
 Read only - ""
Must use $ETrap in trigger code
$ZTRIggerop
 Read only - ""
 Read only
Shows the triggering command
$ZTUPdate
 Read only - ""
 Read only
Lists modified pieces (if requested) for SET
$ZTVAlue
 Read only - ""
 Read / Write
Can change the eventual applied value for SET
$ZTWOrmhole
 Read / Write
 Read / Write
Holds application context because trigger code has no access to the local variable context
$ZTSlate

-

Read/ Write Holds outermost transaction context for chained or nested triggers.

Examples for Trigger ISVs  

Nodes in ^ACN(CID,50) have TYPE in piece 1, CLS in piece 2, FEEPLN in piece 15 and EMPLNO in piece 31. Indexes are ^XACN(CLS,ACN,CID), ^XREF("EMPLCTA",EMPLNO,ACN,TYPE,CID) and ^XREF("FEEPLN",FEEPLN,CID) and use ACN from the first piece of ^ACN(CLS,99). These indexes are maintained with four triggers: one invoked by a KILL or ZKill of an ^ACN(:,50) node and three invoked by SETs to different pieces of ^ACN(:,50) nodes. Note that ACN, CID, CLS and TYPE are required, whereas EMPLNO and FEEPLN can be null, which requires (in our convention) the use of $ZC(254) in indexes.   The triggerfile definitions are:

 
+^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"  

The code in KACN50.m kills cross reference indexes when the application deletes any ^ACN(:,50).    

 

      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

The routine in SclsACN50.m creates cross references for a SET or a SET $Piece() that modifies the second piece of ^ACN(:,50).

 

     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  

 

Note that the example is written for clarity. Eliminating values that need not be assigned to temporary local variables produces:

 

    SClsACN50 ; Update to CLS in ^ACN(,50)

; Capture information 

Set oldcls=$Piece($ZTOLD,"|",2)      ; Old CLS 

Set acn=$Piece(^ACN(cid,99),"|",1) ; ACN 

If $Piece($ZTWORM,"|",1)<2 Do

. Kill ^XACN(oldcls,acn,cid) Set ^XACN($P($ZTVAL,"|",2),acn,cid)=""

Quit


Or for automatically generated code where readability is not important, the routine can be just two lines:

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

Indeed, this index can simply be included in the (one line) triggerfile specification itself:

 
+^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)="""""
 

In the interest of readability most triggerfile definitions in this document are written as complete routines.  The code in SemplnoTypeACN50.m handles changes to pieces 1 and 31 of ^ACN(:,50). Note that a SET to ^ACN(:,50) that modifies either or both pieces causes this trigger to execute just once, whereas two sequential SET $Piece() commands, to first modify one piece and then the other cause it to execute twice, at different times, once for each piece.

 
     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 

The code in SFeeplnACN50.m handles changes to piece 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 D
. Kill ^XREF("FEEPLN",oldfeepln,cid) Set ^XREF("FEEPLN",feepln,cid)=""
Quit

 

トリガエラーメッセージ 

GVDATAGETFAIL

GVDATAGETFAIL, Global variable DATAGET sub-operation (in KILL function) failed. Failure code: cccc.

 

Run Time Trigger Error: The target node for a KILL operation could not present its state to the trigger logic due to a database problem. cccc contains the failure codes for the failed attempts. The database may have integrity errors or the process-private data structures may be corrupted.

 

Action: Report this database error to the group responsible for database integrity at your operation.  


NOZTRAPINTRIG  

NOZTRAPINTRIG, Use of $ZTRAP in a database trigger environment ($ZTLEVEL greater than 0) is not supported.

Run Time Trigger Error: GT.M requires the use of $ETRAP for error handling within trigger logic.

Action: Modify the application code to use $ETRAP to handle errors in trigger logic.
 

SETINTRIGONLY

SETINTRIGONLY, ISV iiii cannot be modified outside of the trigger environment
  
Run Time Trigger Error: The Intrinsic Special variable iiii can only be SET within the context of trigger logic ($ZTLEVEL > 0)
  
Action: Examine the application logic to determine whether code intended for use in a trigger context falls in an execution path outside of trigger logic. For code intended to execute both inside and outside triggers, use a postcondition that limits the SET to within a trigger.

TRIG2NOTRIG

TRIG2NOTRIG, Sending transaction sequence number xxxx which used triggers to a replicator that does not support triggers
  
MUPIP Warning: The source server encountered a transaction that includes triggers, but its replicating node does not support triggers. Unless you are using application level filters to handle this case, your originating instance and replicating instance are no longer consistent.
  
Action: If this case it not handled by your application level filters, you should either enhance your filters or upgrade the replicating instance to a version of GT.M that supports triggers and load the the appropriate trigger definitions with MUPIP TRIGGER (or $ZTRIGGER()), and then take appropriate action (such as recreating the replicating instance from a backup of the originating instance) to restore consistency.  

TRIGCOMPFAIL

TRIGCOMPFAIL, Compilation of database trigger named tttt failed 
 
Run Time Trigger Error: The -Xecute code of a trigger specification has syntax errors. Because triggers are precompiled when you define them, this error may indicate that either:


Action: Validate the definitions by a SELECT option with MUPIP TRIGGER or $ZTRIGGER(), correct the trigger code syntax and apply a trigger update. 

TRIGDATAIGNORE

TRIGDATAIGNORE, Ignoring trigger data tttt. Use MUPIP TRIGGER to load trigger definitions

MUPIP informational message : MUPIP LOAD displays this error when it encounters trigger metadata during extract file processing (GO/ZWR extracts).

Action: Even though the trigger metadata in an extract file is safe, you should only use MUPIP TRIGGER or $ZTRIGGER() to define a trigger.

TRIGDEFBAD

TRIGDEFBAD, Trigger initialization failed for global ^gggg. Error while processing ^#t("xxxx",yyyy[,zzzz])

GT.M/MUPIP error : Missing or corrupted trigger metadata causes this error.

Action:
Delete and replace defective triggers. If possible analyze the cause of the trigger damage and report the incident to your GT.M support channel.

TRIGINVCHSET

TRIGINVCHSET, Trigger tttt for global gggg was created with CHSET=cccc which is different from the current $ZCHSET of this process
  
Run Time Trigger Error: Trigger tttt on global gggg failed because the process that attempted to update global gggg did not have the same character set that was used to load trigger tttt.  Databases with triggers can only be used by processes that are M mode or UTF-8 mode, depending on the mode of the process that loaded the triggers.

Action: Ensure that processes start with the same character set (as defined by the gtm_chset environment variable) that was used to load the trigger definitions with MUPIP TRIGGER (or $ZTRIGGER() function).

TRIGJNLSTATE

TRIGJNLSTATE, Trigger cannot update journaled database file dddd since triggering update was not journaled

Run Time Trigger Error: A process performed an update on a global in a database region which is not currently journaled, and that update invoked a trigger that, in turn, attempted an update on a global in a database region that is journaled. The secondary GVIS message provides the global name. This would produce a journal state with insufficient information to ensure proper replication of the region with the triggered update.

Action: Revise global directories, journaling characteristics, or trigger logic to prevent this situation.  

TRIGNAMEUNIQ

TRIGNAMEUNIQ, Unable to make trigger name tttt unique beyond vvvv versions already loaded

Run Time Trigger Error: GT.M encountered more than vvvv different instances of the same trigger name across database regions used by the same process.

Action: Revise trigger names to prevent such a high degree of overlap.

TRIGSUBSCRANGE


TRIGSUBSCRANGE, Trigger definition for global ^gggg has one or more invalid subscript range(s) : ssss

GT.M/MUPIP error : This error indicates one or more invalid subscript range(s) (not matching collated/non-collated subscript ordering) for global gggg in tthe trigger definition files.

Action: Verify the validity of subscript ranges in trigger definition file for the particular global and reload with correct subscript ranges for the collation of the global in question.

TRIGTCOMMIT

TRIGTCOMMIT, TCOMMIT at $ZTLEVEL=LLLL not allowed as corresponding TSTART was done at lower $ZTLEVEL=BBBB

Run Time Trigger Error: A TCOMMIT in trigger logic attempted to complete the active transaction that was started outside of the current trigger. Because trigger actions are atomic with the update initiating them, committing a transaction started prior to or by the triggering update cannot be committed inside the trigger.

Action: Within the trigger context, review the TCOMMIT logic to ensure that it commits only those transactions that are started within the trigger. Ensure that TCOMMIT does not attempt to commit any transaction started prior to or by the triggering update.  

TRIGTLVLCHNG

TRIGTLVLCHNG, Detected a net transaction level ($TLEVEL) change during trigger tttt. Transaction level must be the same at exit as when the trigger started

Run Time Trigger Error: While the trigger logic can use balanced sub-transactions, it cannot cause a net change in $TLEVEL.

Action: Review the transaction management (TSTART, TCOMMIT and TROLLBACK) within trigger logic to ensure that it commits or rolls back any transactions it starts and does not attempt to commit any transaction started prior to, or by, the trigger update. You can use TROLLBACK within trigger logic to block the current transaction, possibly to write error context information. Nonetheless if you use such a TROLLBACK, GT.M subsequently signals this error when you leave the trigger context in order to notify the process that the original triggering update has been discarded.

ZGOTOINVLVL

ZGOTOINVLVL, ZGOTO in a trigger running in mmmm cannot ZGOTO level LLLL

MUPIP Error: A ZGOTO command in trigger logic attempted to specify an inappropriate destination. Currently that is a ZGOTO in a trigger context with a target level of one (1) and an entryref. GT.M does not support such ZGOTO arguments in MUPIP because there is no context outside that of the trigger.

Action: Revise the trigger logic to only use ZGOTO with an entryref within the trigger context of trigger logic. Note that you can ZGOTO out of a trigger, but doing so in MUPIP terminates the MUPIP process. FIS recommends limiting the use of ZGOTO to debugging, error handling and testing. Use of ZGOTO in production code, even for error processing, should always be thoroughly tested.

ZTRIGINVACT

ZTRIGINVACT, Missing or invalid subcode (first) parameter given to $ZTRIGGER()

Run Time Trigger Error: The first argument to $ZTRIGGER() is required to specify its mode of action.

Action: for the first argument of $ZTRIGGER() use an expression that evaluates to "FILE", "ITEM" or "SELECT".

ZTRIGNOTP

ZTRIGNOTP, $ZTRIGGER() cannot use update subcodes FILE or ITEM when a TP transaction is in progress ($TLEVEL greater than zero)

Run Time Trigger Error: A FILE or ITEM operation of $ZTRIGGER() failed because it attempted to apply a trigger definition inside an ongoing transaction. Both FILE and ITEM operations of $ZTRIGGER initiate an implicit transaction to achieve trigger update atomicity, therefore, GT.M does not allow nesting them inside another transaction that potentially might use the very triggers $ZTRIGGER() is attempting to update.

Action: Move all FILE or ITEM operations of $ZTRIGGER() outside the scope of any open transaction.

ZTWORMHOLE2BIG

ZTWORMHOLE2BIG, String length of LLLL bytes exceeds maximum length of mmmm bytes for $ZTWORMHOLE

Run Time Trigger Error: GT.M limits $ZTWORMHOLE length to mmmm bytes and the application attempted to use LLLL bytes.

Action: Restrict the size of the string stored in $ZTWORMHOLE to mmmm bytes. Ensure that $ZTWORMHOLE only holds the information that the application needs during trigger execution. If necessary, reorganize the logic to reduce the amount of local context needed during trigger execution, possibly by using global variables.



For more information, see the GT.M web site.









notes



1 A trigger definition file is a text file. You can specify any extension of your choice. For consistency across GT.M documentation and  GT.M automated testing systems, we have used .trg as the file extension for a trigger definition file.
inserted by FC2 system