使用 ereport
或其旧形式 elog
创建服务器代码中生成的错误、警告和日志消息。此函数的使用是复杂的,需要一些解释。
每条消息都需要两个必填元素:一个严重级别(范围从 DEBUG
到 PANIC
,定义在 src/include/utils/elog.h
中)和一个主要消息文本。此外,还有一些可选元素,其中最常见的是一个错误标识符代码,遵循 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
(或其等价物)和 errdetail_log
都已使用,则一个字符串发送到客户端,而另一个字符串写入到日志中。这对于过于敏感或过于庞大,不能包含在发送给客户端的报告中的错误详细信息非常有用。
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
消息站点直接调用;相反,它用于 error_context_stack
回调函数中,以提供有关错误发生时的上下文的信息,例如 PL 函数中的当前位置。消息字符串的处理方式与 errmsg
相同。与其他辅助函数不同,这可以每次 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)
可用于指定在邮务日志中消息的 STATEMENT:
部分的抑制。如果消息文本已包含当前语句,则通常适用这种情况。
errhidecontext(bool hide_ctx)
可用于指定在邮务日志中消息的 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)
,则不会产生上述情况;因此,请不要这样做。