pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
服务器代码内生成的错误、警告和日志消息应使用 ereport, 或其更老的近亲 elog 来创建。这一函数的用法相当复杂, 因此需要一些解释。
每条消息都必须包含两个元素:严重性级别(范围从 DEBUG 到 PANIC)以及主消息文本。 此外还可以有可选元素,其中最常见的是遵循 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 插入 strerror 为 errno 当前值返回的错误消息。 [11] %m does not require any corresponding entry in the parameter list for errmsg. Note that the message string will be run through gettext for possible localization before format codes are processed.
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 消息处调用;它用于 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 节。
[11] 也就是说,是到达 ereport 调用点时的那个值; 辅助报告例程内部对 errno 的更改不会影响 它。如果显式写出 strerror(errno) 作为 errmsg 的参数列表内容,就不是这样了;因此不要 这么做。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。