サーバコード内から生成されるエラー、警告、ログメッセージは、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_DIVISION_BY_ZERO), errmsg("division by zero")));
この余分な括弧はPostgreSQLバージョン12より前では必要でしたが、現在ではオプションです。
以下に、より複雑な例を示します。
ereport(ERROR, errcode(ERRCODE_AMBIGUOUS_FUNCTION), errmsg("function %s is not unique", func_signature_string(funcname, nargs, NIL, actual_arg_types)), errhint("Unable to choose a best candidate function. " "You might need to add explicit typecasts."));
これは、実行時の値をメッセージテキスト内に埋め込むための整形用コードの使用を示します。
また、省略可能な「ヒント」メッセージも提供されています。
補助関数の呼び出しは任意の順序で記述できますが、慣習的にerrcode
とerrmsg
が最初に記述されます。
深刻度レベルがERROR
以上であれば、ereport
は現在の問い合わせの実行を中断し、呼び出し元には戻りません。
深刻度レベルがERROR
未満であれば、ereport
は正常に戻ります。
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
で返されるエラーメッセージを挿入することができます。
[16]
%m
はerrmsg
のパラメータリスト内に対応する項目を必要としません。
メッセージ文字列は、書式コードの処理を行う前に、地域化のためにgettext
を通ることに注意してください。
errmsg_internal(const char *msg, ...)
は、そのメッセージ文字列は翻訳されず、国際化用メッセージ辞書に含まれない点を除き、errmsg
と同一です。
これは、おそらく翻訳作業を行う価値がない「発生し得ない」場合用に使用すべきです。
errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n, ...)
はerrmsg
のようですが、メッセージの各種の複数書式があります。
fmt_singular
は英語の単数書式、fmt_plural
は英語の複数書式、n
はどの複数書式が必要なのかを決定する整数値で、残りの引数は選択された書式文字列に従って書式化されます。
より詳細な情報は55.2.2を参照してください。
errdetail(const char *msg, ...)
は省略可能な「詳細」メッセージを提供します。
これは、主メッセージ内に記述するには不適切と考えられる追加情報がある場合に使用されます。
このメッセージ文字列はerrmsg
とまったく同じ方法で処理されます。
errdetail_internal(const char *msg, ...)
は、メッセージが翻訳されない、または、国際化メッセージ辞書内に含まれない点を除き、errdetail
と同じです。
これは、例えばほとんどのユーザに役に立つにはあまりにも技術的すぎるなど、翻訳する手間をかける価値がない詳細メッセージで有用であるはずです。
errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n, ...)
はerrdetail
と似ていますが、メッセージの各種の複数書式をサポートします。
より詳細な情報は55.2.2を参照してください。
この文字列がサーバログのみに渡り、クライアントに渡らない点を除きerrdetail_log(const char *msg, ...)
はerrdetail
と同一です。
errdetail
(や上記の等価物の1つ)とerrdetail_log
が共に使用された場合、1つの文字列はクライアントに渡り、もう1つはログに渡ります。
クライアントに送られるレポートに含めるにはセキュリティに対して慎重を期さなければならないもの、あるいは膨大すぎるエラー詳細に対して効果があります。
errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n, ...)
はerrdetail_log
と似ていますが、メッセージの各種の複数書式をサポートします。
より詳細な情報は55.2.2を参照してください。
errhint(const char *msg, ...)
は、省略可能な「ヒント」メッセージを提供します。
これは、何が悪かったのかについての事実に基づく詳細とは反対で、問題を解決させる方法に関する提言を提供するために使用されます。
このメッセージ文字列はerrmsg
とまったく同じ方法で処理されます。
errhint_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n, ...)
はerrhint
と似ていますが、メッセージの各種の複数書式をサポートします。
より詳細な情報は55.2.2を参照してください。
errcontext(const char *msg, ...)
は通常ereport
メッセージ側から直接呼び出されません。
エラーが発生したコンテキスト、例えばPL関数の現在位置の情報を提供するためにerror_context_stack
コールバック関数内で使用されます。
メッセージ文字列はerrmsg
とまったく同じ方法で処理されます。
他の補助関数とは異なり、1つのereport
呼び出しで何度も呼び出すことができます。
こうして提供される文字列の並びは、改行で区切った形で連結されます。
errposition(int cursorpos)
は、問い合わせ文字列内でエラーが発生した位置をテキストで指定します。
現在、問い合わせ処理の字句解析および構文解析段階でエラーが検出された場合にのみ役に立ちます。
errtable(Relation rel)
はエラーレポートにおいて名前とスキーマ名が外部フィールドとして含まれなければならないリレーションを指定します。
errtablecol(Relation rel, int attnum)
はエラーレポートにおいて名前、テーブル名、およびスキーマ名が外部フィールドとして含まれなければならない列を指定します。
errtableconstraint(Relation rel, const char *conname)
はエラーレポートにおいて名前、テーブル名、およびスキーマ名が外部フィールドとして含まれなければならないテーブル制約を指定します。
この目的のため、関連したpg_constraint
エントリの有る無しに関わらず、インデックスは制約と見なされなければなりません。進行中のヒープリレーションを受け渡すにはインデックスではなくrel
とすることに注意してください。
errdatatype(Oid datatypeOid)
はエラーレポートにおいて名前とスキーマ名が外部フィールドとして含まれなければならないデータ型を指定します。
errdomainconstraint(Oid datatypeOid, const char *conname)
はエラーレポートにおいて名前、ドメイン名、およびスキーマ名が外部フィールドとして含まれなければならないドメイン制約を指定します。
errcode_for_file_access()
は、ファイルアクセス関連のシステムコールでの失敗用のSQLSTATEエラー識別子を適切に選択する、便利な関数です。
保存されたerrno
を使用して、どのエラーコードを生成するかを決定します。
通常、これは主エラーメッセージテキスト内で%m
と組み合わせて使用されなければなりません。
errcode_for_socket_access()
は、ソケット関連のシステムコールでの失敗用のSQLSTATEエラー識別子を適切に選択する、便利な関数です。
errhidestmt(bool hide_stmt)
は、postmasterのログ内のメッセージにおけるSTATEMENT:
部分を抑制するために呼び出すことができます。
通常これは、メッセージテキスト内にすでに現在の文が含まれている場合に適しています。
errhidecontext(bool hide_ctx)
は、postmasterのログ内のメッセージにおけるCONTEXT:
部分を抑制するために呼び出すことができます。
これは、冗長なデバッグメッセージにおいてコンテキストを繰り返し含めることがログのサイズを巨大にしてしまうような場合にのみ用いられるべきです。
ereport
呼び出しにおいて、最大限でもerrtable
、errtablecol
、 errtableconstraint
、errdatatype
、またはerrdomainconstraint
のうちの一つの関数が使用されなければなりません。
これらの関数は、アプリケーションが自動エラー対応であって欲しいと期待するエラーレポートにおいて使用されるべきです。
PostgreSQL 9.3の時点で、この機能を完璧に保証する範囲はSQLSTATEクラス23(整合性制約違反)のみですが、将来的には十中八九拡張されそうです。
まだ頻繁に使用されている、古めのelog
関数があります。
以下のelog
呼び出しは、
elog(level, "format string", ...);
以下とまったく同じです。
ereport(level, errmsg_internal("format string", ...));
SQLSTATEエラーコードが常にデフォルトになること、メッセージ文字列が翻訳されないことに注意してください。
したがって、elog
は、内部エラーと低レベルなデバッグ用ログにのみ使用すべきです。
一般ユーザを対象とする任意のメッセージはereport
を使用すべきです。
それでもなお、システム内の「発生できなかった」内部エラーの検査にelog
がまだ多く使用されています。
これは、こうした単純な表記のメッセージに適しています。
54.3に推奨するエラーメッセージの作成についての提言を示します。
[16]
つまり、ereport
呼び出しに達した時点の値です。
補助報告ルーチン内でerrno
を変更しても効果はありません。
errmsg
内でstrerror(errno)
を明示的に記述したとしても正確なものにはなりません。
したがって、このようにはしないでください。