サーバ内部からのエラーの報告

PostgreSQL 9.1.1文書
前のページ | 巻戻し | 第 47章PostgreSQLコーディング規約 | 早送り | 次のページ

# 47.2. サーバ内部からのエラーの報告

サーバコード内から生成されるエラー、警告、ログメッセージは、`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,
                                          NIL, actual_arg_types)),
             errhint("Unable to choose a best candidate function. "
                     "You might 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`と同一です。 これは、おそらく翻訳作業を行う価値がない"発生できなかった"場合用に使用すべきです。

- `errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n, ...)`は`errmsg`のようですが、メッセージの各種の複数書式があります。 `fmt_singular`は英語の単数書式、`fmt_plural`は英語の複数書式、`n`はどの複数書式が必要なのかを決定する整数値で、残りの引数は選択された書式文字列に従って書式化されます。 より詳細な情報は項48.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`と似ていますが、メッセージの各種の複数書式をサポートします。 より詳細な情報は項48.2.2を参照してください。

- この文字列がサーバログのみに渡り、クライアントに渡らない点を除き`errdetail_log(const char *msg, ...)`は`errdetail`と同一です。 `errdetail`（や上記の等価物の１つ）と`errdetail_log`が共に使用された場合、１つの文字列はクライアントに渡り、もう１つはログに渡ります。 クライアントに送られるレポートに含めるにはセキュリティに対して慎重を期さなければならないもの、あるいは膨大すぎるエラー詳細に対して効果があります。

- `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エラー識別子を適切に選択する、便利な関数です。

- `errhidestmt(bool hide_stmt)`は、postmasterのログ内のメッセージにおける`STATEMENT:`部分を抑制するために呼び出すことができます。 通常これは、メッセージテキスト内にすでに現在の文が含まれている場合に適しています。

まだ頻繁に使用されている、古めの`elog`関数があります。 以下の`elog`呼び出しは、

    elog(level, "format string", ...);

以下とまったく同じです。

    ereport(level, (errmsg_internal("format string", ...)));

SQLSTATEエラーコードが常にデフォルトになること、メッセージ文字列が変換されないことに注意してください。 したがって、`elog`は、内部エラーと低レベルなデバッグ用ログにのみ使用すべきです。 一般ユーザを対象とする任意のメッセージは`ereport`を使用すべきです。 それでもなお、システム内の"発生できなかった"内部エラーの検査に`elog`がまだ多く使用されています。 これは、こうした単純な表記のメッセージに適しています。

項47.3に推奨するエラーメッセージの作成についての提言を示します。

### 注意

[1] | つまり、`ereport`呼び出しに達した時点の値です。 補助報告ルーチン内で`errno`を変更しても効果はありません。 `errmsg`内で`strerror(errno)`を明示的に記述したとしても正確なものにはなりません。 したがって、このようにはしないでください。

前のページ | ホーム | 次のページ
書式 | 上に戻る | エラーメッセージのスタイルガイド