选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.0 已于 2015 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

47.2. 在服务器内部报告错误 #

服务器代码内生成的错误、警告和日志消息应使用 ereport, 或其更老的近亲 elog 来创建。这一函数的用法相当复杂, 因此需要一些解释。

每条消息都必须包含两个元素:严重性级别(范围从 DEBUGPANIC)以及主消息文本。 此外还可以有可选元素,其中最常见的是遵循 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 插入 strerrorerrno 当前值返回的错误消息。 [12] %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_log(const char *msg, ...)errdetail 相同,只是该字符串只会写入服务器日志, 绝不会发送给客户端。如果同时使用 errdetailerrdetail_log,那么一条字符串会发往客户端,另一条 会发往日志。对于那些因安全性过于敏感或内容过于庞大而不适合 放入发给客户端的报告中的错误细节,这很有用。

  • errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n, ...) 类似于 errdetail, 但支持消息的各种复数形式。更多信息见 第 48.2.2 节

  • errhint(const char *msg, ...) 提供一条可选的 提示消息;当要就如何修复问题给出建议(而非关于 出了什么问题的事实性详情)时,可使用它。消息字符串的处理方式 与 errmsg 完全相同。

  • errcontext(const char *msg, ...) 通常不会直接在 ereport 消息处调用;它用于 error_context_stack 回调函数中,提供错误发生时的 上下文信息,例如 PL 函数中的当前位置。消息字符串的处理方式与 errmsg 完全相同。与其他辅助函数不同,它在每次 ereport 调用中可以被调用多次;这样提供的 successive 字符串会用换行符分隔拼接起来。

  • 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 节



[12] 也就是说,是到达 ereport 调用点时的那个值; 辅助报告例程内部对 errno 的更改不会影响 它。如果显式写出 strerror(errno) 作为 errmsg 的参数列表内容,就不是这样了;因此不要 这么做。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。