サーバコード内から生成されるエラー、警告、ログメッセージは、ereport、もしくはこれに似た古いelogを使用して作成してください。 この関数の使用は、いくつか説明が必要なほど複雑です。
全てのメッセージには、深刻度レベル(DEBUGからPANICまでの範囲)と主メッセージテキストという、2つの必須要素があります。 更に、省略可能な要素があります。 その中で最も良く使用されるのは、SQL仕様のSQLSTATE規則に従うエラー識別コードです。 ereport自身はシェル関数で、主に、メッセージ生成をCソースコード内の関数呼び出しのように行なわせる、構文の便宜上存在します。 ereportで直接受け付けられる唯一のパラメータは深刻度レベルです。 主メッセージテキストと任意の省略可能なメッセージ要素は、ereport呼び出し内でerrmsgなどの補助関数を呼び出すことで生成されます。
典型的なereportの呼び出しは以下のようなものです。
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO), errmsg("division by zero")));
これは、エラー深刻度レベルERROR(普通のエラー)を指定します。 errcode呼び出しは、src/include/utils/errcodes.hで定義されたマクロを使用してSQLSTATEエラーコードを指定します。 errmsg呼び出しは、主メッセージテキストを提供します。 補助関数呼び出しを囲む余計な括弧群に注意してください。 これらはいらいらさせられますが、構文上必要です。
以下により複雑な例を示します。
ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_FUNCTION), errmsg("function %s is not unique", func_signature_string(funcname, nargs, actual_arg_types)), errhint("Unable to choose a best candidate function. " "You may need to add explicit typecasts.")));
これは、実行時の値をメッセージテキスト内に埋め込むための整形用コードの使用を示します。 また、省略可能な"ヒント"メッセージも提供されています。
ereportで使用可能な補助ルーチンを以下に示します。
errcode(sqlerrcode)は、その条件用のSQLSTATEエラー識別コードを指定します。 このルーチンが呼び出されないと、エラー識別子のデフォルトは、エラー深刻度レベルがERROR以上の場合にはERRCODE_INTERNAL_ERRORに、エラー深刻度レベルがWARNINGの場合にはERRCODE_WARNINGに、さもなければ(NOTICE以下)ERRCODE_SUCCESSFUL_COMPLETIONになります。 これらのデフォルトはしばしば便利ですが、errcode()呼び出しを省略する前に、常に適切かどうかを検討してください。
errmsg(const char *msg, ...)は、主エラーメッセージテキストを指定し、また、実行時の値をそこに挿入することもできます。 挿入は、sprintf様式の書式コードで指定されます。 sprintfで受け付けられる標準の書式コードに加え、%m書式コードを使用して、現在のerrnoの値用のstrerrorで返されるエラーメッセージを挿入することができます。 [1] %mはerrmsgのパラメータリスト内に対応する項目を必要としません。 メッセージ文字列は、書式コードの処理を行なう前に、地域化のためにgettextを通ることに注意してください。
errmsg_internal(const char *msg, ...)は、そのメッセージ文字列には国際化用メッセージ辞書が含まれない点を除き、errmsgと同一です。 これは、おそらく翻訳作業を行なう価値がない"発生できなかった"場合用に使用すべきです。
errdetail(const char *msg, ...)は、省略可能な"詳細"メッセージを提供します。 これは、主メッセージ内に記述するには不適切と考えられる追加情報がある場合に使用されます。 このメッセージ文字列はerrmsgと全く同じ方法で処理されます。
errhint(const char *msg, ...)は、省略可能な"ヒント"メッセージを提供します。 これは、何が悪かったのかについての事実に基づく詳細とは反対で、問題を解決させる方法に関する提言を提供するために使用されます。 このメッセージ文字列はerrmsgと全く同じ方法で処理されます。
errcontext(const char *msg, ...)は通常ereportメッセージサイトから直接呼び出されません。 エラーが発生したコンテキスト、例えばPL関数の現在位置、の情報を提供するためにerror_context_stackコールバック関数内で使用されます。 メッセージ文字列はerrmsgと全く同じ方法で処理されます。 他の補助関数とは異なり、1つのereport呼び出しで何度も呼び出すことができます。 こうして提供される文字列の並びは、改行で区切った形で連結されます。
errposition(int cursorpos)は、問い合わせ文字列内でエラーが発生した位置をテキストで指定します。 現在、問い合わせ処理の字句解析および構文解析段階でエラーが検出された場合にのみ役に立ちます。
errcode_for_file_access()は、ファイルアクセス関連のシステムコールでの失敗用のSQLSTATEエラー識別子を適切に選択する、便利な関数です。 保存されたerrnoを使用して、どのエラーコードを生成するかを決定します。 通常、これは主エラーメッセージテキスト内で%mと組み合わせて使用されなければなりません。
errcode_for_socket_access()は、ソケット関連のシステムコールでの失敗用のSQLSTATEエラー識別子を適切に選択する、便利な関数です。
まだ頻繁に使用されている、古めのelog関数があります。 以下のelog呼び出しは、
elog(level, "format string", ...);
以下と全く同じです。
ereport(level, (errmsg_internal("format string", ...)));
SQLSTATEエラーコードが常にデフォルトになること、メッセージ文字列内に国際化メッセージ辞書を含めることができないことに注意してください。 従って、elogは、内部エラーと低レベル名デバッグ用ログにのみに使用すべきです。 一般ユーザを対象とする任意のメッセージはereportを使用すべきです。 それでもなお、システム内の"発生できなかった"内部エラーの検査にelogがまだ多く使用されています。 これは、こうした単純な表記のメッセージに適しています。
項43.3に推奨するエラーメッセージの作成についての提言を示します。
[1] | つまり、ereport呼び出しに達した時を現在とした値です。 補助報告ルーチン内でerrnoを変更しても効果はありません。 errmsg内でstrerror(errno)を明示的に記述したとしても正確なものにはなりません。 従って、このようにはしないでください。 |