エラー処理
エラー発生時の Caché の振る舞いを管理することを、エラー処理 といいます。エラー処理では、以下の機能の 1 つまたは複数が実行されます。
-
エラーの原因となる条件の修正
-
エラー発生後に動作を再開させるための処理の実行
-
実行フローの変更
Caché は、次の 3 種類のエラー処理の方法をサポートしており、これらを同時に使用することもできます。
ObjectScript のエラー処理には、TRY-CATCH メカニズムが推奨されます。また、従来のエラー処理を使用する場合には、$ZTRAP メカニズムが推奨されます。$ETRAP の使用は、お勧めしません。
TRY-CATCH メカニズム
Caché は、エラー処理のために TRY-CATCH メカニズムをサポートします。このメカニズムを使用すると、それぞれが TRY ブロックと呼ばれる区切られたコードのブロックを作成できます。TRY ブロック中にエラーが発生した場合、TRY ブロックに関連付けられた、例外処理のコードを含む CATCH ブロックに制御が渡されます。TRY ブロックには THROW コマンドを含めることもできます。これらのコマンドはそれぞれ、TRY ブロック内から明示的に例外を発行し、実行を CATCH ブロックに移します。
最も基本的な形式でこのメカニズムを使用するには、ObjectScript コード内に TRY ブロックを含めます。このブロック内で例外が発生する場合、関連付けられた CATCH ブロック内のコードが実行されます。TRY-CATCH ブロックの形式は以下のとおりです。
TRY {
protected statements
} CATCH [ErrorHandle] {
error statements
}
further statements
以下はその説明です。
-
TRY コマンドは、中括弧で囲まれた ObjectScript のコード文を識別します。TRY は引数を取りません。このコード・ブロックは、構造化された例外処理のための保護されたコードです。TRY ブロック内で例外が発生した場合、Caché は例外プロパティ (oref.Name、oref.Code、oref.Data、oref.Location)、$ZERROR、および $ECODE を設定し、CATCH コマンドによって識別される、例外ハンドラに実行を移します。これは、例外のスローとして知られています。
-
protected statementsは、通常の実行の一部である、ObjectScript 文です。(これらの文には、THROW コマンドへの呼び出しを含めることができます。このシナリオについては、以下のセクションで説明します。)
-
CATCH コマンドは、例外ハンドラを定義します。これは、TRY ブロックで例外が発生したときに実行されるコードのブロックです。
-
ErrorHandle 変数は、例外オブジェクトへのハンドルです。これは、Caché が実行時エラーに対して生成した例外オブジェクト、または THROW コマンド (以下のセクションで説明します) の呼び出しにより明示的に発行された例外オブジェクトのいずれかとなります。
-
error statements は、例外が発生したときに呼び出される ObjectScript 文です。
-
further statements は、例外がない場合に protected statements の実行の後に続く、または例外が発生して CATCH ブロックから制御が渡される場合に error statements の実行の後に続く、ObjectScript 文です。
protected statements の実行中のイベントに応じて、以下のイベントのいずれかが発生します。
-
エラーが発生しない場合、CATCH ブロックの外側に表示される further statements で実行が続行します。
-
エラーが発生する場合、制御が CATCH ブロックに渡され、error statements が実行されます。実行は、CATCH ブロックの内容によって異なります。
-
CATCH ブロックに THROW コマンドまたは GOTO コマンドが含まれている場合、指定された場所に制御が直接移動します。
-
CATCH ブロックに THROW コマンドまたは GOTO コマンドが含まれていない場合、CATCH ブロックから制御が渡され、further statements で実行が続行します。
-
TRY-CATCH と一緒に THROW を使用する
Caché は、実行時エラーの発生時に暗黙的な例外を発行します。明示的な例外を発行するには、THROW コマンドを使用できます。THROW コマンドは、TRY ブロックから CATCH 例外ハンドラへ実行を移します。THROW コマンドの構文は以下のとおりです。
THROW expression
expression は、例外処理のために Caché に用意されている %Exception.AbstractExceptionOpens in a new tab クラスから継承するクラスのインスタンスです。%Exception.AbstractExceptionOpens in a new tab の詳細は、以下のセクションを参照してください。
TRY/CATCH ブロックと THROW を一緒に発行する場合の形式は以下のとおりです。
TRY {
protected statements
THROW expression
protected statements
}
CATCH exception {
error statements
}
further statements
ここで、THROW コマンドは明示的に例外を発行します。TRY-CATCH ブロックの他の要素については、前のセクションで説明しています。
THROW の動作は、スローが発生する場所と THROW の引数によって異なります。
-
TRY ブロック内の THROW は、CATCH ブロックに制御を渡します。
-
CATCH ブロック内の THROW は、実行スタックの制御を次のエラー・ハンドラに渡します。例外が %Exception.SystemException オブジェクトの場合、次のエラー・ハンドラは、どのタイプ (CATCH または従来のエラー処理) でもかまいません。それ以外の場合は、CATCH による例外処理が必要となります。そうしないと、<NOCATCH> エラーがスローされます。
引数付きの THROW のために、制御が CATCH ブロックに渡される場合、ErrorHandle には引数からの値が含まれています。システム・エラーのために制御が CATCH ブロックに渡される場合、ErrorHandle は %Exception.SystemExceptionOpens in a new tab オブジェクトです。ErrorHandle が指定されていない場合、制御が CATCH ブロックに渡された理由が示されません。
例えば、以下のように 2 つの数字を除算するコードがあるとします。
div(num,div) public {
TRY {
SET ans=num/div
} CATCH errobj {
IF errobj.Name="<DIVIDE>" { SET ans=0 }
ELSE { THROW errobj }
}
QUIT ans
}
0 による除算エラーが発生すると、このコードは結果として 0 を返すように特別に設計されています。この他のエラーの場合、THROW はスタック上のエラーを次のエラー・ハンドラに送信します。
$$$ThrowOnError および $$$ThrowStatus マクロの使用法
Caché は、例外処理で使用するために、マクロを提供します。これらのマクロは、呼び出されると CATCH ブロックに例外オブジェクトをスローします。
以下の例は、%Prepare() メソッドによりエラー・ステータスが返されると、$$$ThrowOnError マクロを呼び出します。
#Include %occStatus
ZNSPACE "SAMPLES"
TRY {
SET myquery = "SELECT TOP 5 Name,Hipness,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
$$$ThrowOnError(status)
WRITE "%Prepare succeeded",!
RETURN
}
CATCH sc {
WRITE "In Catch block",!
WRITE "error code: ",sc.Code,!
WRITE "error location: ",sc.Location,!
WRITE "error data:",$LISTGET(sc.Data,2),!
RETURN
}
以下の例は、%Prepare() メソッドにより返されたエラー・ステータスの値をテストした後に$$$ThrowStatus を呼び出します。
#Include %occStatus
ZNSPACE "SAMPLES"
TRY {
SET myquery = "SELECT TOP 5 Name,Hipness,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
IF ($System.Status.IsError(status)) {
WRITE "%Prepare failed",!
$$$ThrowStatus(status) }
ELSE {WRITE "%Prepare succeeded",!
RETURN }
}
CATCH sc {
WRITE "In Catch block",!
WRITE "error code: ",sc.Code,!
WRITE "error location: ",sc.Location,!
WRITE "error data:",$LISTGET(sc.Data,2),!
RETURN
}
システム指定のマクロについては、このドキュメントの “ObjectScript マクロとマクロ・プリプロセッサ” の章で説明します。
%Exception.SystemException と %Exception.AbstractException クラスの使用
Caché は、例外処理で使用するために、%Exception.SystemExceptionOpens in a new tab クラスと %Exception.AbstractExceptionOpens in a new tab クラスを提供しています。%Exception.SystemExceptionOpens in a new tab は %Exception.AbstractExceptionOpens in a new tab クラスから継承しており、システム・エラーに使用されます。カスタム・エラーの場合、%Exception.AbstractExceptionOpens in a new tab から継承するクラスを作成します。%Exception.AbstractExceptionOpens in a new tab には、エラーの名前や、エラーが発生した場所などのプロパティが含まれています。
システム・エラーが TRY ブロック内でキャッチされると、システムは %Exception.SystemExceptionOpens in a new tab クラスの新しいインスタンスを作成し、そのインスタンス内にエラー情報を配置します。アプリケーション・プログラマは、カスタム例外をスローするとき、オブジェクトにエラー情報を入れる責任があります。
例外オブジェクトには、以下のプロパティがあります。
-
Name — <UNDEFINED> などのエラー名。
-
Code — エラー番号
-
Location — エラーの label+offset^routine の場所
-
Data — エラーによって報告される任意の追加データ (エラーの原因となる項目の名前など)
TRY-CATCH を使用する際の他の考慮事項
TRY-CATCH ブロックを使用する際に発生する可能性がある状況を、以下に説明します。
TRY または CATCH ブロック内の QUIT コマンドは、TRY-CATCH ブロック全体の後で、ブロックから次の文に制御を渡します。
TRY ブロックは、実行スタックで新しいレベルを導入しません。つまり、NEW コマンドのアクセス範囲境界ではありません。error statements は、そのエラーと同じレベルで実行されます。この結果として、protected statements 内に DO コマンドがあり、DO のターゲットも protected statements 内にある場合には、予期しない結果が発生する可能性があります。このような場合には、$ESTACK 特殊変数が、相対的な実行レベルに関する情報を提供できます。
TRY-CATCH エラー処理は、実行スタックの異なるレベルで使用される $ZTRAP エラー・トラップと $ZTRAP エラー・トラップと互換性があります。例外は、$ZTRAP と $ETRAP を TRY 節の protected statements 内で使用できないことです。THROW コマンドでは、ユーザ定義のエラーは TRY-CATCH のみに制限されます。ZTRAP コマンドを使用したユーザ定義のエラーは、任意のタイプのエラー処理で使用できます。
%Status エラー処理
Caché クラス・ライブラリのメソッドの多くは、%StatusOpens in a new tab データ型を使用して、成功、または失敗の情報を返します。例えば、%PersistentOpens in a new tab オブジェクトのインスタンスを保存するときに使用される %Save() メソッドは、オブジェクトが保存されたか否かを示す %StatusOpens in a new tab 値を返します。
-
メソッドの実行が成功すると、1 の %StatusOpens in a new tab が返ります。
-
メソッドの実行が失敗すると、エラー・ステータスおよび 1 つ以上のエラー・コードとテキスト・メッセージを含むエンコードされた文字列として %StatusOpens in a new tab が返ります。ステータス・テキスト・メッセージはユーザのロケールの言語でローカライズされています。
%SYSTEM.StatusOpens in a new tab クラス・メソッドを使用すれば、%StatusOpens in a new tab の値を検査および操作できます。
Caché には、%StatusOpens in a new tab でエンコードされた文字列をさまざまな形式で表示 (書き込み) するための複数のオプションがあります。詳細は、このドキュメントの “コマンド” の章の “表示 (書き込み) コマンド” を参照してください。
以下の例では、myquery テキストのエラーによって %Prepare が失敗します (“ZOP” は “TOP” とすべき)。このエラーは IsError()Opens in a new tab メソッドにより検出され、他の %SYSTEM.StatusOpens in a new tab がエラー・コードとテキストを表示します。
ZNSPACE "SAMPLES"
SET myquery = "SELECT ZOP 5 Name,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
IF ($System.Status.IsError(status)) {
WRITE "%Prepare failed",!
DO StatusError() }
ELSE {WRITE "%Prepare succeeded",!
RETURN }
StatusError()
WRITE "Error #",$System.Status.GetErrorCodes(status),!
WRITE $System.Status.GetOneStatusText(status,1),!
WRITE "end of error display"
QUIT
下の例は上の例と同じですが、ステータス・エラーが %occStatus インクルード・ファイルの $$$ISERR() マクロによって検出される点で異なります。$$$ISERR() (およびその反転型である $$$ISOK()) は、%StatusOpens in a new tab =1 であるかどうかをチェックします。エラー・コードは $$$GETERRORCODE() マクロによって返されます。
#Include %occStatus
ZNSPACE "SAMPLES"
SET myquery = "SELECT ZOP 5 Name,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
IF $$$ISERR(status) {
WRITE "%Prepare failed",!
DO StatusError() }
ELSE {WRITE "%Prepare succeeded",!
RETURN}
StatusError()
WRITE "Error #",$$$GETERRORCODE(status),!
WRITE $System.Status.GetOneStatusText(status,1),!
WRITE "end of error display"
QUIT
システム指定のマクロについては、このドキュメントの “ObjectScript マクロとマクロ・プリプロセッサ” の章で説明します。
%New() など、%StatusOpens in a new tab を生成しても返さないメソッドもあります。%New() は、成功時にはクラスのインスタンスに oref を返し、失敗時には NULL 文字列を返します。以下の例で示すように、%objlasterror システム変数にアクセスして、この種のメソッドのステータス値を取得することができます。
SET session = ##class(%CSP.Session).%New()
IF session="" {
WRITE "session oref not created",!
WRITE "%New error is ",!,$System.Status.GetErrorText(%objlasterror),! }
ELSE {WRITE "session oref is ",session,! }
詳細は、%SYSTEM.StatusOpens in a new tab のクラスを参照してください。
%Status エラーの作成
Error()Opens in a new tab メソッドを使用すれば、ユーザ独自のメソッドからシステム定義の %Status エラーを呼び出すことができます。この場合、返したいエラー・メッセージに対応するエラー番号を指定します。
WRITE "Here my method generates an error",!
SET status = $System.Status.Error(20)
WRITE $System.Status.GetErrorText(status),!
以下の例で示すように、返すエラー・メッセージに %1、%2、%3 パラメータを含むことができます。
WRITE "Here my method generates an error",!
SET status = $System.Status.Error(214,"3","^fred","BedrockCode")
WRITE $System.Status.GetErrorText(status),!
エラー・メッセージをローカライズして、ユーザの優先言語で表示することもできます。
SET status = $System.Status.Error(30)
WRITE "In English:",!
WRITE $System.Status.GetOneStatusText(status,1,"en"),!
WRITE "In French:",!
WRITE $System.Status.GetOneStatusText(status,1,"fr"),!
エラー・コードとメッセージ (英語) の一覧については、"Caché エラー・リファレンス" の “一般的なエラー・メッセージ” の章を参照してください。
一般的なエラー・コード 83 および 5001 を使用すれば、いずれの一般エラー・メッセージにも対応していないカスタム・メッセージを指定することができます。
また、AppendStatus()Opens in a new tab メソッドを使用して、複数のエラー・メッセージの一覧を作成することができます。さらに、GetOneErrorText()Opens in a new tab または GetOneStatusText()Opens in a new tab を使用して、この一覧のそれぞれの位置ごとの各エラー・メッセージを取得することもできます。
CreateCustomErrors
SET st1 = $System.Status.Error(83,"my unique error")
SET st2 = $System.Status.Error(5001,"my unique error")
SET allstatus = $System.Status.AppendStatus(st1,st2)
DisplayErrors
WRITE "All together:",!
WRITE $System.Status.GetErrorText(allstatus),!!
WRITE "One by one",!
WRITE "First error format:",!
WRITE $System.Status.GetOneStatusText(allstatus,1),!
WRITE "Second error format:",!
WRITE $System.Status.GetOneStatusText(allstatus,2),!
%SYSTEM.Error
%SYSTEM.ErrorOpens in a new tab クラスは一般的なエラー・オブジェクトです。これは %Status エラー、例外オブジェクト、$ZERROR エラー、または SQLCODE エラーから作成することができます。%SYSTEM.ErrorOpens in a new tab クラス・メソッドを使用すれば、%Status を例外に、または例外を %Status に変換することができます。
従来のエラー処理
このセクションでは、Caché を使用した従来のエラー処理のさまざまな側面について説明します。以下の内容が含まれます。
従来のエラー処理の概要
Caché には、アプリケーションでエラー・ハンドラを使用して従来のエラー処理を実行できるようにするための機能が備わっています。エラー・ハンドラは、アプリケーションの実行中に発生するあらゆるエラーを処理します。エラー発生時に実行する ObjectScript コマンドは、特殊変数で指定します。これらのコマンドは、エラーを直接処理するか、エラーを処理するルーチンを呼び出します。
エラー・ハンドラの作成には、以下の基本的な処理を実行します。
-
エラー処理を実行する 1 つ以上のルーチンを生成します。エラー処理を実行するコードを作成します。このコードは、アプリケーション全体に対する一般的なコードであっても、特定の処理における特定のエラー状態に対するものであってもかまいません。これにより、アプリケーションの特定個所で、カスタマイズされたエラー処理を実行できます。
-
アプリケーション内に 1 つ以上のエラー・ハンドラを設定し、それぞれのエラー・ハンドラで固有の適切なエラー処理を使用します。
エラーが発生してもエラー・ハンドラが設定されていなかった場合の振る舞いは、その Caché セッション の開始方法によって異なります。
-
Caché にプログラマ・モードでサインオンし、エラー・トラップを設定していない場合、主デバイスにエラー・メッセージを表示し、プログラム・スタックの設定を変更せずにプログラマ・モードに入ります。プログラマは、プログラムの実行を後で再開できます。
-
アプリケーション・モードで Caché を実行し、エラー・トラップを設定していない場合、Caché は主デバイスにエラー・メッセージを表示し、HALT コマンドを実行します。
内部的なエラー・トラップの振る舞い
特殊変数 $ZTRAP (および $ETRAP) による Caché のエラー処理とその有効範囲を最大限に活用するには、Caché が制御をあるルーチンから別のルーチンに移す方法を理解すると役立ちます。
Caché は、以下のいずれかが発生するたびに、“コンテキスト・フレーム” というデータ構造を構築します。
-
ルーチンが Do コマンドで別のルーチンを呼び出す場合 (この種類のフレームは “DO フレーム” とも呼ばれます)。
-
XECUTE コマンド引数により、ObjectScript コードが実行される場合 (この種類のフレームは “XECUTE フレーム” とも呼ばれます)。
-
ユーザ定義関数を実行した場合
プロセスのアドレス部にあるプライベート・データ構造の 1 つ、コール・スタックにフレームが構築されます。Caché はルーチン用として、フレームに以下の要素を格納します。
-
$ZTRAP 特殊変数の値 (存在する場合)
-
$ETRAP 特殊変数の値 (存在する場合)
-
サブルーチンから返される位置情報
例えば、ルーチン A がルーチン B を DO ^B で呼び出すと、Caché は、コール・スタックに A のコンテキストを保持する Do フレームを構築します。また、ルーチン B がルーチン C を呼び出すと、コール・スタックに B のコンテキストを保持する Do フレームを追加します。
上図のルーチン A が Do コマンドを使用してプログラマ・モード・プロンプトで呼び出される場合、図にはありませんが、追加の Do フレームがコール・スタックの一番下に存在しています。
現在のコンテキスト・レベル
現在のコンテキスト・レベルに関する情報を返すために以下を使用できます。
-
$STACK 特殊変数は、現在の相対スタック・レベルを含みます。
-
$ESTACK 特殊変数は、現在のスタック・レベルを含みます。任意のユーザ定義のポイントで、0 (レベル・ゼロ) に初期化できます。
-
$STACK 関数は、現在のコンテキストと、コール・スタックに格納されているコンテキストに関する情報を返します。
$STACK 特殊変数
$STACK 特殊変数は、プロセスのコール・スタックに現在保存されているフレームの数を含みます。$STACK 値は、基本的に、現在実行しているコンテキストの (ゼロ・ベースの) レベル番号です。したがって、Caché イメージが開始されるとき、コマンドが処理されるまで、$STACK の値は 0 です。
詳細は、"Caché ObjectScript リファレンス" の "$STACK" 特殊変数を参照してください。
$ESTACK 特殊変数
$ESTACK 特殊変数は、$STACK 特殊変数に類似していますが、New コマンドで変数を 0 にリセットできるため (また以前の値を保存できます)、エラー処理には $ESTACK の方が便利です。したがって、プロセスは、特定のコンテキストで $ESTACK をリセットし、$ESTACK レベル 0 のコンテキストとしてマークすることができます。その後エラーが発生した場合、エラー・ハンドラは $ESTACK 値をテストし、コール・スタックをそのコンテキストまで戻すことができます。
詳細は、"Caché ObjectScript リファレンス" の "$ESTACK" 特殊変数を参照してください。
$STACK 関数
$STACK 関数は、現在のコンテキストと、コール・スタックに格納されているコンテキストに関する情報を返します。各コンテキストで、$STACK 関数は以下の情報を提供します。
-
コンテキスト・タイプ (Do、Xecute、ユーザ定義関数)
-
コンテキストで処理された最後のコマンドのエントリ参照とコマンド番号
-
コンテキストで処理された最後のコマンドを含むソース・ルーチン行あるいは XECUTE 文字列
-
コンテキストで発生した任意のエラーの $ECODE 値 ($ECODE が NULL でない場合、エラー処理中にのみ利用可能)
エラー発生時、すべてのコンテキスト情報はプロセス・エラー・スタックに即座に格納されます。その後、コンテキスト情報は、エラー・ハンドラが $ECODE 値をクリアするまで $STACK 関数によりアクセスできます。つまり、$ECODE 値が NULL でない場合、$STACK 関数は、エラー・スタックに保存されたコンテキストと同じ指定されたコンテキスト・レベルのアクティブなコンテキストではなく、エラー・スタックに保存されたコンテキストの情報を返します。
詳細は、"Caché ObjectScript リファレンス" の "$STACK" 関数を参照してください。
エラーが発生し、エラー・スタックが既に存在している場合、Caché は、エラー・スタックの同じコンテキスト・レベルに別のエラー情報が存在しない限り、コンテキスト・レベルで新しいエラーに関する情報を記録します。この場合、エラー情報は、(エラー情報が既に記録されているか否かにかかわらず) エラー・スタックの次のレベルに配置されます。
したがって、新規エラーのコンテキスト・レベルによっては、エラー・スタックは拡張される (1 つ以上のコンテキスト・レベルを追加される) か、あるいは、既存のエラー・スタックのコンテキスト・レベルに存在する情報が新規エラー情報を格納するために上書きされることがあります。
$ECODE 特殊変数をクリアすると、プロセス・エラー・スタックが消去されることに注意してください。
エラー・コード
エラー発生時、Caché は $ZERROR 特殊変数と $ECODE 特殊変数に、エラーを示す値を設定します。
$ZERROR 値
Caché は、$ZERROR に以下を含む文字列を設定します。
-
山括弧で囲まれた Caché のエラー・コード
-
エラー発生場所のラベル、オフセットおよびルーチン名
-
一部のエラーでは、エラーの原因となった項目の名前などの追加情報
%Exception.SystemExceptionOpens in a new tab クラスの AsSystemError()Opens in a new tab メソッドは、$ZERROR と同じ形式で同じ値を返します。
以下の例では、Caché がエラーに遭遇した際に、$ZERROR に設定されるメッセージ・タイプを示します。以下の例では、未定義のローカル変数 abc が、ルーチン MyTest のラベル PrintResult より行オフセット 2 の位置で呼び出されます。$ZERROR は以下を含みます。
<UNDEFINED>PrintResult+2^MyTest *abc
存在しないクラスが行オフセット 3 の位置で実行されると、以下のエラーが発生します。
<CLASS DOES NOT EXIST>PrintResult+3^MyTest *%SYSTEM.XXQL
既存クラスの存在しないメソッドが行オフセット 4 の位置で実行されると、以下のエラーが発生します。
<METHOD DOES NOT EXIST>PrintResult+4^MyTest *BadMethod,%SYSTEM.SQL
128 文字までの任意の文字列として、特殊変数 $ZERROR を明示的に設定することもできます。以下はその例です。
SET $ZERROR="Any String"
$ZERROR の値は、エラーのすぐ後に続けて使用することを意図したものです。$ZERROR の値は複数のルーチン呼び出しにわたって保持することができないため、$ZERROR の値を後で使用できるように保持したいユーザは、値を変数にコピーする必要があります。$ZERROR は、使用直後に NULL 文字列 ("") に設定することを強くお勧めします。詳細は、"Caché ObjectScript リファレンス" の "$ZERROR" 特殊変数を参照してください。$ZERROR エラーの取り扱いについての詳細は、"インターシステムズ・クラス・リファレンス" の %SYSTEM.ErrorOpens in a new tab クラス・メソッドを参照してください。
$ECODE 値
エラー発生時、Caché は $ECODE に、コンマに囲まれた文字列値を設定します。この値は、エラーに対応する ANSI 標準エラー・コードを含んでいます。例えば、未定義のグローバル変数を参照する場合、Caché は $ECODE セットに以下の文字列を設定します。
,M7,
エラーに対応する ANSI 標準エラー・コードを持たない場合、Caché は文字 Z が先頭についた Caché エラー・コードを含む、コンマに囲まれた文字列値に $ECODE を設定します。例えば、プロセスがシンボル・テーブルの領域をすべて使用した場合、Cachéは $ZERROR 特殊変数にエラー・コード <STORE> を置き、$ECODE に以下の文字列を設定します。
,ZSTORE,
エラー発生後、エラー・ハンドラは $ZERROR 特殊変数あるいは $ECODE 特殊変数を検証して、特定のエラー・コードをテストできます。
エラー・ハンドラは、特定のエラーに関し、$ECODE 特殊変数ではなく $ZERROR 特殊変数を検証する必要があります。
詳細は、"Caché ObjectScript リファレンス" の "$ECODE" 特殊変数を参照してください。
$ZTRAP でのエラー処理
$ZTRAP でエラーを処理するには、$ZTRAP 特殊変数を location に設定し、引用符で囲まれた文字列として指定します。$ZTRAP 特殊変数はエントリ参照に対して設定します。このエントリ参照によって、エラー発生時における制御の移管先となる location を指定します。次にその場所に $ZTRAP コードを記述します。
$ZTRAP を空でない値に設定した場合、いずれの既存 $ETRAP エラー・ハンドラよりも優先となります。Caché は、暗黙的に NEW $ETRAP コマンドを実行し、$ETRAP に "" を設定します。
プロシージャでの $ZTRAP の設定
プロシージャ内では、そのプロシージャ内の行ラベル (プライベート・ラベル) にのみ $ZTRAP 特殊変数を設定できます。プロシージャ・ブロック内部から $ZTRAP を外部ルーチンに設定することはできません。
$ZTRAP 値を表示するとき、Caché はプライベート・ラベルの名前を返しません。代わりに、プロシージャの先頭からのそのプライベート・ラベルがある場所までのオフセットを返します。
詳細は、"ObjectScript リファレンス" の "$ZTRAP" 特殊変数を参照してください。
ルーチンでの $ZTRAP の設定
ルーチン内では、$ZTRAP 特殊変数を現在のルーチンのラベル、外部ルーチン、または外部ルーチン内のラベルに設定できます。外部ルーチンを参照できるのは、そのルーチンがプロシージャ・ブロック・コードでない場合だけです。以下の例では、LogErr^ErrRou をエラー・ハンドラとして構築します。エラー発生時には、Caché が ^ErrRou ルーチン内の LogErr ラベルにあるコードを実行します。
SET $ZTRAP="LogErr^ErrRou"
$ZTRAP 値を表示するとき、Caché はラベル名と (該当する場合には) ルーチン名を表示します。
ラベル名は最初の 31 文字内で一意である必要があります。ラベル名およびルーチン名では、大文字と小文字が区別されます。
ルーチン内では、$ZTRAP には 3 つの形式があります。
-
SET $ZTRAP="location"
-
SET $ZTRAP="*location"。この形式では、この関数を呼び出したエラーの発生元であるコンテキストで実行されます。
-
SET $ZTRAP="^%ETN" は、システムで提供されるエラー・ルーチン %ETN を実行します。このルーチンはルーチンを呼び出すエラーが発生したコンテキストにおいて実行されます。プロシージャ・ブロックから ^%ETN (または外部ルーチン) を実行することはできません。コードを [Not ProcedureBlock] として指定するか、または %ETN エントリポイント BACK^%ETN を呼び出す以下のようなルーチンを使用します。
ClassMethod MyTest() as %Status { SET $ZTRAP="Error" WRITE 5/0 /* divide-by-zero error */ WRITE "Exiting ##class(User.A).MyTest()" QUIT Error SET err=$ZERROR SET $ZTRAP="" DO BACK^%ETN QUIT $$$ERROR($$$CacheError,err) }
%ETN およびそのエントリポイントの詳細は、"アプリケーション・エラーのロギング" を参照してください。$ZTRAP と共に使用する場合の詳細は、SET $ZTRAP=^%ETN を参照してください。
詳細は、"ObjectScript リファレンス" の "$ZTRAP" 特殊変数を参照してください。
$ZTRAP コードの記述
$ZTRAP が指し示す location はさまざまな操作を実行して、エラーを表示、ログ記録、または修正することができます。実行したいエラー処理操作の如何にかかわらず、$ZTRAP コードは以下の 2 つのタスクの実行により開始する必要があります。
-
$ZTRAP を他の値、すなわちエラー・ハンドラの location または空文字列 ("") のいずれかに設定します。(KILL $ZTRAP. とすることはできないので、SET を使用する必要があります。)これを行う理由は、エラー処理中に別のエラーが発生した場合において、そのエラーが現在の $ZTRAP エラー・ハンドラを呼び出してしまうためです。現在のエラー・ハンドラがユーザの関わるエラー・ハンドラである場合、無限ループとなってしまいます。
-
ある変数を $ZERROR に設定します。後からコードで $ZERROR の値を参照したい場合は、$ZERROR そのものではなく、この変数を参照してください。これを行う理由は、$ZERROR が最新のエラーを含んでおり、$ZERROR の値は、内部ルーチン呼び出しを含む複数のルーチン呼び出しにわたって保持することができないためです。エラー処理中に別のエラーが発生した場合、$ZERROR の値がその新しいエラーによって上書きされることになります。
$ZERROR は、使用直後に NULL 文字列 ("") に設定することを強くお勧めします。
以下の例では、これらの不可欠な $ZTRAP コード文を示します。
MyErrHandler
SET $ZTRAP=""
SET err=$ZERROR
/* error handling code
using err as the error
to be handled */
$ZTRAP の使用法
アプリケーションの各ルーチンは、$ZTRAP を設定して、独自の $ZTRAP エラー・ハンドラを作成できます。エラー・トラップの発生時、Caché は以下の手順を実行します。
-
特殊変数 $ZERROR にエラー・メッセージを設定します。
-
プログラム・スタックを、エラー・トラップが設定された時点 (SET $ZTRAP= の実行時) の状態にリセットします。つまり、システムは、エラー・トラップが設定された時点まで、スタックに存在するすべてのエントリを削除します。($ZTRAP がアスタリスク (*) で始まる文字列に設定されている場合、プログラム・スタックはリセットされません。)
-
$ZTRAP の値により指定された位置でプログラムを再開します。$ZTRAP の値は保持されます。
Note:$ZERROR 変数を、128 文字までの文字列として明示的に設定できます。通常、$ZERROR は null 文字に設定しますが、$ZERROR を値に設定してもかまいません。
エラー・トラップによる New コマンドの削除
エラー・トラップが発生しプログラム・スタック・エントリが削除されると、Caché は、スタックされたすべての NEW コマンドも削除し、SET $ZTRAP= を含むサブルーチン・レベルに戻します。しかし、NEW コマンドが $ZTRAP の設定前あるいは設定後にスタックに追加されたかどうかにかかわらず、そのサブルーチン・レベルで実行されたすべての NEW コマンドは維持されます。
以下はその例です。
Main
SET A=1,B=2,C=3,D=4,E=5,F=6
NEW A,B
SET $ZTRAP="ErrSub"
NEW C,D
DO Sub1
RETURN
Sub1()
NEW E,F
WRITE 6/0 // Error: division by zero
RETURN
ErrSub()
WRITE !,"Error is: ",$ZERROR
WRITE
RETURN
Sub1 のエラーがエラー・トラップを起動した場合、Sub1 にスタックされた E と F における以前の値は削除されます。しかし、A、B、C、D はスタックされたままになります。
$ZTRAP フロー制御オプション
$ZTRAP エラー・ハンドラがエラー処理のために呼び出され、クリーンアップとエラー記録処理を実行した後、このエラー・ハンドラには 3 つのフロー制御オプションがあります。
-
エラーを処理し、アプリケーションを継続します。
-
制御を別のエラー・ハンドラに渡します。
-
アプリケーションを終了します。
アプリケーションの継続
$ZTRAP がエラーを処理した後には、GOTO の発行によりアプリケーションを続行することができます。通常のアプリケーション処理を継続するために、$ZERROR または $ECODE 特殊変数値をクリアする必要はありません。しかし、$ZTRAP をクリアし (空の文字列を設定)、別のエラーが発生した際に無限のエラー処理ループに入らないようにする必要があります。詳細は、“エラー・ハンドラによるエラー処理” を参照してください。
エラー処理を実行した後、$ZTRAP エラー・ハンドラは GOTO コマンドを使用して、アプリケーション内で事前設定されたリスタートまたは継続ポイントに制御を移し、通常のアプリケーション処理を再開できます。
エラー・ハンドラがエラーを処理すると、$ZERROR 特殊変数が値に設定されます。エラー・ハンドラが処理を終了すると、この値は必ずしもクリアされるわけではありません。エラー・ハンドラを呼び出すエラーが次に発生したときに、$ZERROR は上書きされます。この理由から、$ZERROR 値はエラー・ハンドラのコンテキスト内でのみ使用する必要があります。その他のコンテキストで $ZERROR を使用すると、信頼できる結果が生成されません。
別のエラー・ハンドラへの制御の移動
エラー条件を $ZTRAP エラー・ハンドラで修正できない場合、特殊な形式の ZTRAP コマンドを使用して、別のエラー・ハンドラに制御を移すことができます。コマンド ZTRAP $ZERROR は、エラー条件を再度示し、エラー・ハンドラを使って、Caché で次のコール・スタック・レベルまでコール・スタックが戻るようにします。Caché で次のエラー・ハンドラのレベルにコール・スタックを戻したら、そのエラー・ハンドラで処理が続行します。次のエラー・ハンドラは、$ZTRAP または $ETRAP で設定された可能性があります。
下図は、$ZTRAP エラー処理ルーチンのフロー制御を示しています。
$ETRAP でのエラー処理
$ETRAP を設定している場合にエラー・トラップが発生すると、Caché は以下の手順を実行します。
-
$ECODE と $ZERROR の値を設定します。
-
$ETRAP の値であるコマンドを処理します。
既定では、各 DO、XECUTE、ユーザ定義関数のコンテキストは、それを呼び出したフレームの $ETRAP エラー・ハンドラを継承します。つまり、任意のコンテキスト・レベルで指定された $ETRAP エラー・ハンドラは、その定義が現在よりも下位レベルから生成された場合も、最新の $ETRAP 定義になります。
$ETRAP エラー・ハンドラ
$ETRAP 特殊変数は、エラー発生時に実行される 1 つ以上の ObjectScript コマンドを含むことができます。SET コマンドを使用して、エラー処理ルーチンに制御を移す 1 つ以上の Caché コマンドを持つ文字列に、$ETRAP を設定できます。この例では、LogError コード・ラベル (ErrRoutine ルーチンの一部) に制御を移します。
SET $ETRAP="DO LogError^ErrRoutine"
$ETRAP 特殊変数のコマンドには、常に暗黙の QUIT コマンドが続きます。暗黙の QUIT コマンドは、$ETRAP エラー・ハンドラが、引数付きの QUIT コマンドを必要とするユーザ定義関数コンテキストで呼び出されている場合、NULL 文字列の引数で終了します。
$ETRAP の範囲はグローバルです。つまり、$ETRAP 設定の前は、通常 NEW $ETRAP になります。そうしないと、$ETRAP の値が現在のコンテキストで設定される場合、このコンテキストの範囲を超えた後でも、制御がレベルの高いコンテキストにある状態で、$ETRAP に格納された値が存在し続けます。このため、NEW $ETRAP を指定しない場合、設定されたコンテキストがなくなると、$ETRAP は予期しないときに実行されることがあります。
詳細は、"Caché ObjectScript リファレンス" の "$ETRAP" 特殊変数を参照してください。
コンテキスト固有の $ETRAP エラー・ハンドラ
以下の手順を実行して、すべてのコンテキストで独自の $ETRAP エラー・ハンドラを作成できます。
-
NEW コマンドを使用して、$ETRAP の新規コピーを生成します。
-
$ETRAP に新しい値を設定します。
ルーチンが、最初に $ETRAP の新規コピーを生成せずに $ETRAP を設定すると、新規 $ETRAP エラー・ハンドラは、現在のコンテキスト、呼び出したコンテキストに対して作成され、場合によっては、コール・スタックに保存された他のコンテキストに対して作成されることもあります。したがってインターシステムズは、$ETRAP を設定する前にその新規コピーを生成することをお勧めします。
$ETRAP の新規コピーを作成しても、$ETRAP は削除されないことに注意してください。$ETRAP の値は、NEW コマンドを発行しても変更されずに維持されます。
以下の "$ETRAP エラー・ハンドラ" 図は、$ETRAP エラー・ハンドラのスタックを生成する $ETRAP の割り当て順序を示しています。以下は図の説明です。
-
ルーチン A は、$ETRAP の新規コピーを生成し、その新規コピーに “GoTo ^ERR” を設定します。また、ルーチン B を呼び出す Do コマンドが含まれています。
-
ルーチン B は $ETRAP に何も作用しません (その結果、ルーチン A の $ETRAP エラー・ハンドラを継承します)。また、ルーチン C を呼び出す Do コマンドが含まれています。
-
ルーチン C は、$ETRAP の新規コピーを生成し、その新規コピーに “GOTO ^CERR” を設定します。また、ルーチン D を呼び出す Do コマンドが含まれています。
-
ルーチン D は、$ETRAP の新規コピーを生成し、その後コピーをクリアします。その結果、コンテキストには $ETRAP エラー・ハンドラは残されません。
エラーがルーチン D ($ETRAP エラー・ハンドラが未定義のコンテキスト) で発生した場合、Caché はルーチン D の DO フレームをコール・スタックから削除し、ルーチン C の $ETRAP エラー・ハンドラに制御を移します。次にルーチン C の $ETRAP エラー・ハンドラは、エラーを処理するために ^CERR に移動します。ルーチン C でエラーが発生した場合、Caché はルーチン C の $ETRAP エラー・ハンドラに制御を移します。しかし、$ETRAP エラー・ハンドラを定義したコンテキストでエラーが発生しているため、スタックは戻されません。
$ETRAP フロー制御オプション
$ETRAP エラー・ハンドラがエラーを処理し、任意のクリーンアップとエラー記録処理を実行するために呼び出された場合、以下のフロー制御オプションがあります。
-
エラーを処理し、アプリケーションを継続します。
-
制御を別のエラー・ハンドラに渡します。
-
アプリケーションを終了します。
エラー処理とアプリケーションの継続
$ETRAP エラー・ハンドラがエラー処理のために呼び出された場合、Caché は、エラー条件が解消されるまで、そのエラーは有効であると判断します。$ECODE 特殊変数に NULL 文字列を設定し、エラー条件を解消します。
SET $ECODE=""
$ECODE をクリアすると、プロセスのエラー・スタックもクリアします。
通常、GOTO コマンドを使用して、エラー条件の解消後に、アプリケーションであらかじめ設定されたリスタート位置、あるいは継続位置に制御を移します。場合によっては、エラー条件の解消後に元のコンテキスト・レベルに戻ったほうが便利なこともあります。
別のエラー・ハンドラへの制御の移動
エラー条件が解消されない場合、Caché は、QUIT コマンドによって $ETRAP エラー・ハンドラが呼び出されたコンテキストが終了されたときに、コール・スタック上の別のエラー・ハンドラに制御を移します。したがって、$ECODE をクリアせずに QUIT コマンドを $ETRAP コンテキストから実行することにより、以前のレベルのエラー・ハンドラに制御を渡します。
ルーチン C から呼び出されたルーチン D に ^CERR に制御を移すエラーが存在した場合、$ECODE を "" (空の文字列) に設定する式が前に置かれていない ^CERR で QUIT コマンドを発行すると、以前のコンテキスト・レベルの $ETRAP エラー・ハンドラに制御が移ります。一方、$ECODE をクリアしてエラー条件を解消した場合、^CERR から QUIT コマンドを発行すると、DO ^C コマンドに続くルーチン B の文に制御が移ります。
アプリケーションの終了
以前のレベルのエラー・ハンドラがコール・スタックに存在し、$ETRAP エラー・ハンドラが、エラー条件を解消せずに QUIT コマンドを実行すると、アプリケーションは終了します。その後、アプリケーション・モードで Caché は停止し、制御はオペレーティング・システムに移ります。プログラマ・モードで、プログラマ・モード・プロンプトが表示されます。
エラー条件が解消されたかどうかにかかわらず、QUIT コマンドを使用して $ETRAP エラー・ハンドラ・コンテキストを終了する必要があります。引数なしの QUIT と引数付きの QUIT(ユーザ定義関数コンテキスト) を必要とするコンテキスト・レベルで同じ $ETRAP エラー・ハンドラを呼び出すことができるため、特定のコンテキスト・レベルで必要な QUIT コマンド形式を示すために、$QUIT 特殊変数が提供されています。
$QUIT 特殊変数は、引数付きの QUIT が必要なコンテキストに対して 1 を、引数なしの QUIT が必要なコンテキストに対して 0 を返します。
$ETRAP エラー・ハンドラは $QUIT を使用して、以下のいずれかの環境を提供できます。
Quit:$QUIT "" Quit
適宜、$ETRAP エラー・ハンドラは、HALT コマンドを使用してアプリケーションを終了できます。
エラー・ハンドラによるエラー処理
エラー・ハンドラでエラーが発生するとき、実行フローは、現在実行中のエラー・ハンドラ・タイプにより異なります。
$ETRAP エラー・ハンドラでのエラー
$ETRAP エラー・ハンドラで新規エラーが発生した場合、Caché は、$ETRAP エラー・ハンドラが呼び出されたコンテキスト・レベルが削除されるまで、コール・スタックを戻します。その後 Caché は、(存在する場合) コール・スタック上の次のエラー・ハンドラに制御を渡します。
$ZTRAP エラー・ハンドラでのエラー
$ZTRAP エラー・ハンドラで新規エラーが発生すると、Caché は、最初に検出したエラー・ハンドラに制御を渡し、必要に応じてコール・スタックを戻します。したがって、$ZTRAP エラーが現在のスタック・レベルで $ZTRAP をクリアせず、別のエラーが同じエラー・ハンドラで続けて発生した場合、$ZTRAP ハンドラが同じコンテキスト・レベルで再度呼び出されるため、無限ループの原因となります。これを回避するには、エラー・ハンドラの開始時点において $ZTRAP に他の値を設定します。
$ZERROR 特殊変数と $ECODE 特殊変数のエラー情報
元のエラーの処理中に別のエラーが発生した場合、2 番目のエラー情報により、$ZERROR 特殊変数の最初のエラー情報が置き換えられます。しかし、Caché は、$ECODE 特殊変数に新規情報を追加します。2 番目のコンテキスト・レベルによっては、Caché は新規エラー情報を、プロセス・エラー・スタックに追加する場合もあります。
$ECODE 特殊変数の既存の値が NULL 以外の場合、Caché は、新しいコンマ区切りの部分として、新規エラー・コードを現在の $ECODE 値に追加します。以下のいずれかの状況が発生するまで、$ECODE 特殊変数にエラー・コードが追加されます。
-
以下のようにして、$ECODE を明示的にクリアします。
SET $ECODE = ""
-
$ECODE の長さは、最大文字列長を超えています。
その後、次の新規エラー・コードにより、$ECODE にある現在のエラー・コード・リストが置き換えられます。
エラーが発生し、エラー・スタックが既に存在している場合、Caché は、エラー・スタックの同じコンテキスト・レベルに別のエラー情報が存在しない限り、コンテキスト・レベルで新しいエラーに関する情報を記録します。この場合、エラー情報は、(エラー情報が既に記録されているかどうかにかかわらず) エラー・スタックの次のレベルに配置されます。
したがって、新規エラーのコンテキスト・レベルによっては、エラー・スタックは拡張される (1 つ以上のコンテキスト・レベルを追加される) か、あるいは、既存のエラー・スタックのコンテキスト・レベルに存在する情報が新規エラー情報を格納するために上書きされることがあります。
$ECODE 特殊変数をクリアすると、プロセス・エラー・スタックが消去されることに注意してください。
詳細は、"Caché ObjectScript リファレンス" の "$ECODE" 特殊変数と "$ZERROR" 特殊変数を参照してください。$ZERROR エラーの取り扱いについての詳細は、"インターシステムズ・クラス・リファレンス" の %SYSTEM.ErrorOpens in a new tab クラス・メソッドを参照してください。
強制エラー
$ECODE 特殊変数を設定、あるいは ZTRAP コマンドを使用して、制御環境でエラーを発生させます。
$ECODE の設定
$ECODE 特殊変数に NULL 以外の文字列を設定し、エラーを発生させることができます。ルーチンで $ECODE に NULL 以外の文字列を設定すると、Caché は $ECODE に特定の文字列を設定し、その後、エラー状態を生成します。この状況で $ZERROR 特殊変数は、以下のエラー・テキストと共に設定されます。
<ECODETRAP>
その後、通常のアプリケーション・エラーのように、エラー・ハンドラに制御を渡します。
エラー・ハンドラにロジックを追加し、$ECODE の設定により発生させるエラーをチェックできます。エラー・ハンドラは、<ECODETRAP> エラー (例えば、“$ZE["ECODETRAP"” に対して $ZERROR をチェックするか、または選択する特定の文字列値に対して $ECODE をチェックできます。
アプリケーション固有エラーの生成
$ECODE の ANSI 標準フォーマットは、1 つ以上のコンマに囲まれたエラー・コードのリストです。
-
接頭語 “Z” 付きのエラーは、実装固有のエラーです。
-
接頭語 “U” 付きのエラーは、アプリケーション固有のエラーです。
エラー・ハンドラで $ECODE に接頭語 “U” を持つ適切なエラー・メッセージを設定し、ANSI 標準に合う独自のエラー・コードを生成できます。
SET $ECODE=",Upassword expired,"
プログラマ・モードのエラー処理
エラー・ハンドラ・セットを持たないプログラム・モードで Caché にサインオンした後エラーを生成する場合、Caché は、入力したコード行でエラーが発生すると、以下の手順を実行します。
-
Caché は、プロセスの主デバイスで、エラー・メッセージを表示します。
-
エラーが発生したコール・スタック・レベルで中断します。
-
プロセスがプログラマ・モードになります。
エラー・メッセージ形式の理解
エラー・メッセージとして、Caché は以下の 3 行を表示します。
-
エラーが発生したすべてのソース・コード行
-
ソース・コードの行の下で、エラーが発生したコマンドを指定するキャレット (^)
-
$ZERROR のコンテンツを含む行
以下のターミナル・プロンプトの例では、2 番目の SET コマンドに未定義のローカル変数エラーがあります。
USER>WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED> *zzz
USER>
以下の例では、ターミナル・プロンプトから実行される mytest という名前のプログラムにコードと同じ行があります。
USER>DO ^mytest
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>
この場合、$ZERROR は、mytest の中で WriteOut という名前のラベルから 2 行のオフセット位置でエラーが発生したことを示しています。プロンプトが変わり、プログラマ・モードになっていることに注意してください。
プログラマ・モード・プロンプトの理解
既定で、ターミナル・プロンプトは現在のネームスペース名を示します。トランザクションが 1 つ以上開いている場合、$TLEVEL トランザクション・レベル・カウントも含まれます。ZNSPACE コマンドの説明に従って、既定のプロンプトを異なる内容で構成することができます。以下の例は、それらの既定の設定を示します。
USER>
TL1:USER>
ルーチンの実行中にエラーが発生すると、プログラマ・モードを開始するプログラム・スタックをシステムは保存します。以下のような拡張プロンプトが表示されます。
USER 2d0>
この拡張プロンプトは、プログラム・スタックに 2 つのエントリがあり、その最後の方が DO (d で示されています) の呼び出しであることを示しています。このエラーにより、プログラム・スタックに 2 つのエントリが置かれることに注意してください。次の DO 実行エラーにより、以下のプロンプト結果となります。
USER 4d0>
説明の詳細は、“コマンド行ルーチンのデバッグ” の章の "プログラマ・モードのプロンプト情報の理解" を参照してください。
エラーのリカバリ
以下のいずれかの手順を実行できます。
-
プログラマ・モードでコマンドを発行します。
-
変数とグローバル・データを表示、修正します。
-
エラーと他のルーチンを含むルーチンを編集します。
-
他のルーチンを実行します。
これらの手順により、別のエラーを発生させる可能性もあります。
これらの手順の実行後、実行を再開する、あるいはプログラム・スタックの一部/すべてを削除することをお勧めします。
次に続くコマンドでの実行の再開
プログラマ・モードで引数なしの GOTO を入力すれば、エラーを引き起こしたコマンドの次のコマンドで実行を再開できます。
USER>DO ^mytest
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>GOTO
world
USER>
別の行での実行の再開
プログラマ・モードでラベル引数付きの GOTO を発行すると、別の行で実行を再開できます。
USER 2d0>GOTO ErrSect
プログラム・スタックの削除
プログラマ・モードで引数なしの QUIT コマンドを発行すると、プログラム・スタック全体を削除できます。
USER 4d0>QUIT
USER>
プログラム・スタックの部分削除
整数の引数付きの QUIT n コマンドを発行すると、最後の (または最後にある複数の) プログラム・スタック・エントリを削除できます。
USER 8d0>QUIT 1
USER 7E0>QUIT 3
USER 4d0>QUIT 1
USER 3E0>QUIT 1
USER 2d0>QUIT 1
USER 1S0>QUIT 1
USER>
この例では、プログラム・エラーによって 2 つのプログラム・スタック・エントリが作成されているので、GOTO を発行して実行を再開するには、“d” スタック・エントリに移動している必要があります。他に発生する内容に応じて、“d” スタック・エントリは偶数 (USER 2d0>) または奇数 (USER 3d0>) となります。
NEW $ESTACK を使用すれば、指定のプログラム・スタック・レベルで終了できます。
USER 4d0>NEW $ESTACK
USER 5E1>
/* more errors create more stack frames */
USER 11d7>QUIT $ESTACK
USER 4d0>
NEW $ESTACK コマンドにて、エントリが 1 つプログラム・スタックに追加されます。
アプリケーション・エラーのロギング
Caché では、複数の方法で例外をアプリケーション・エラー・ログに記録できます。
-
%ETN ユーティリティでエラーをログに記録する。このユーティリティは、^%ETN として呼び出すか、そのエントリポイントである FORE^%ETN、BACK^%ETN、または LOG^%ETN のいずれかを使用して呼び出すことができます。
%ETN を使用したアプリケーション・エラーのログ
%ETN ユーティリティは、例外をアプリケーション・エラー・ログに記録して終了します。%ETN (またはそのエントリポイントの 1 つ) はユーティリティとして呼び出すことができます。
DO ^%ETN
あるいは、$ZTRAP 特殊変数を %ETN (またはそのエントリポイントの 1 つ) に設定できます。
SET $ZTRAP="^%ETN"
%ETN またはそのエントリポイントの 1 つを指定できます。
-
FORE^%ETN (フォアグラウンド) は、例外を標準のアプリケーション・エラー・ログに記録し、HALT で終了します。これによって、ロールバック処理が呼び出されます。これは、%ETN と同じ処理です。
-
BACK^%ETN (バックグラウンド) は、例外を標準のアプリケーション・エラー・ログに記録し、QUIT で終了します。この場合、ロールバック処理は呼び出されません。
-
LOG^%ETN は、例外を標準のアプリケーション・エラー・ログに記録し、QUIT で終了します。この場合、ロールバック処理は呼び出されません。例外は、標準の %Exception.SystemExceptionOpens in a new tab またはユーザ定義の例外です。
例外を定義するには、LOG^%ETN を呼び出す前に $ZERROR を意味のある値に設定します。この値は、ログ・エントリのエラー・メッセージ・フィールドとして使用されます。ユーザ定義例外を LOG^%ETN 内に直接指定することもできます。その場合、DO LOG^%ETN("This is my custom exception") のように指定します。この値は、ログ・エントリのエラー・メッセージ・フィールドとして使用されます。$ZERROR を NULL 文字列に設定すると (SET $ZERROR="")、LOG^%ETN によって <LOG ENTRY> エラーがログに記録されます。$ZERROR を <INTERRUPT> に設定すると (SET $ZERROR="<INTERRUPT>")、LOG^%ETN によって <INTERRUPT LOG> エラーがログに記録されます。
LOG^%ETN は、$HOROLOG 日付とエラー番号の 2 つの要素が含まれる %List 構造を返します。
以下の例では、推奨されるコーディング方法である、$ZERROR を直ちに変数にコピーする方法を使用しています。LOG^%ETN は %List 値を返します。
SET err=$ZERROR
/* error handling code */
SET rtn = $$LOG^%ETN(err)
WRITE "logged error date: ",$LIST(rtn,1),!
WRITE "logged error number: ",$LIST(rtn,2)
管理ポータルを使用したアプリケーション・エラー・ログの表示
管理ポータルから、[システム処理] を選択し、[システムログ]→[アプリケーションエラーログ] を選択します。アプリケーション・エラー・ログが存在するネームスペースの [ネームスペース] リストが表示されます。ヘッダを使用してリストをソートできます。
アプリケーション・エラー・ログが存在する日付を表示するネームスペースの [日付]、およびその日付に対して記録されているエラーの番号を選択します。ヘッダを使用してリストをソートできます。[フィルタ] を使用して、文字列を [日付] および [数量] の値にマッチさせることができます。
特定の日付のエラーを表示するには、その日付の [エラー] を選択します。エラー # の整数は、日時順にエラーに割り当てられます。エラー # *COM は、その日付のすべてのエラーに適用されるユーザ・コメントです。ヘッダを使用してリストをソートできます。[フィルタ] を使用して文字列をマッチさせることができます。
エラーの [詳細] を選択して、[エラー詳細] ウィンドウを表示します。このウィンドウには、特殊変数の値と [スタック] の詳細を含む、エラー発生時の状態情報が表示されます。個々のエラーにユーザ・コメントを指定できます。
[ネームスペース]、[日付]、および [エラー] のリストにはチェックボックスがあり、これを使用して、対応する 1 つまたは複数のエラーのエラー・ログを削除できます。削除するエラー・ログにチェックを付けてから、[削除] ボタンを選択します。
%ERN を使用したアプリケーション・エラー・ログの表示
%ERN ユーティリティは、%ETN エラー・トラップ・ユーティリティによって記録されたアプリケーション・エラーを検証します。%ERN は、現在のネームスペースについてログに記録されたすべてのエラーを返します。
%ERN ユーティリティを使用するには、以下の手順を実行します。
-
ターミナル・プロンプトで、DO ^%ERN を実行します。ユーティリティの名前では大文字と小文字が区別されます。ユーティリティ内でのプロンプトへの応答では大文字と小文字は区別されません。どのプロンプトでも、「?」と入力するとプロンプトの構文オプションのリストを表示でき、「?L」と入力すると、定義されているすべての値のリストを表示できます。Enter キーを使用すると、終了して前のレベルに戻ることができます。
-
For Date: このプロンプトで、エラーが発生した日付を入力します。%DATE ユーティリティで受け付けられる任意の日付形式を使用できます。年を省略した場合は、現在の年と想定されます。日付と、その日付についてログに記録されたエラーの番号が返されます。または、次の構文を使用して、このプロンプトからエラーのリストを取得できます。
-
?L は、エラーが発生したすべての日付を、新しい順に、ログに記録されたエラーの番号と共にリストします。(T) 列は何日前かを示します。(T) は今日を表し、(T-7) は 7 日前を表します。該当する日のすべてのエラーにユーザ・コメントが定義されている場合、ユーザ・コメントは角括弧で囲んで表示されます。リストの表示後、再び For Date: プロンプトが表示されます。日付または「T-n」を入力できます。
-
[text は、部分文字列 text が含まれるエラーをすべてリストします。<text は、エラー名の構成要素に部分文字列 text が含まれるエラーをすべてリストします。^text は、エラーの場所の構成要素に部分文字列 text が含まれるエラーをすべてリストします。リストの表示後、再び For Date: プロンプトが表示されます。日付を入力します。
-
-
Error: このプロンプトで、検証したいエラーの整数番号を入力します。該当する日の最初のエラーは「1」、2 番目のエラーは「2」というように入力します。または、疑問符 (?) を入力して使用可能な応答のリストを表示します。エラーに関して、エラー名、エラーの場所、時刻、システム変数名、およびエラー発生時に実行されていたコードの行の情報が表示されます。
Error: プロンプトで * を指定すると、コメントを表示できます。* により、該当する日のすべてのエラーに適用される、現在のユーザが指定したコメントが表示されます。その後、新しいコメントを入力して該当するすべてのエラーの既存のコメントを置換するためのプロンプトが表示されます。
-
Variable: このプロンプトで、変数に関する情報のさまざまなオプションを指定できます。ローカル変数の名前 (添え字なしまたは添え字付き) を指定した場合、%ERN は、その変数のスタック・レベルと値 (定義されている場合)、およびそのすべての下位ノードを返します。グローバル変数、プロセス・プライベート変数、または特殊なシステム変数は指定できません。
「?」と入力すると、Variable: プロンプトの他の構文オプションをリストできます。
-
*A: Variable: プロンプトで指定した場合、Device: プロンプトが表示され、Return を押すと、現在のターミナル・デバイスに結果が表示されます。
-
*V: Variable: プロンプトで指定した場合、Variable(s): プロンプトが表示されます。このプロンプトで、添え字なしの 1 つのローカル変数、または添え字なしの複数のローカル変数のカンマ区切りリストを指定します。添え字付きの変数は拒否されます。その後、Device: プロンプトが表示され、Return を押すと、現在のターミナル・デバイスに結果が表示されます。%ERN は、指定した各変数の値 (定義されている場合) と、そのすべての下位ノードを返します。
-
%ER は %ERN の従来の名前です。これらの機能は同じですが、%ERN のほうが多少効率性に優れています。