Postgresql 中文操作指南

56.2. Reporting Errors Within the Server #

服务器代码中生成的错误、警告和日志消息应使用 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_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."));

这说明了使用格式代码将运行时值嵌入到消息文本中的用法。此外,提供了可选的“提示”消息。辅助函数调用可以按任何顺序编写,但通常 errcodeerrmsg 会先出现。

如果严重性级别为 ERROR 或更高,ereport 将中止当前查询的执行,且不返回给调用者。如果严重性级别低于 ERRORereport 将正常返回。

ereport 可用的辅助例程有:

Note

ereport 调用中,最多只能使用一个 errtableerrtablecolerrtableconstrainterrdatatypeerrdomainconstraint 函数。这些函数的存在是为了允许应用程序提取与错误条件相关联的数据库对象名称,而无需检查潜在的本地化错误消息文本。这些函数应在错误报告中使用,应用程序可能希望自动处理错误。截至 PostgreSQL 9.3,仅 SQLSTATE 类 23(完整性约束冲突)的错误有完整的覆盖,但将来可能会扩展此功能。

有一个仍然大量使用的旧函数 elog。一个 elog 调用:

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

完全等同于:

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

请注意,SQLSTATE 错误代码始终为默认值,且消息字符串不受翻译。因此,elog 应该仅用于内部错误和低级调试日志记录。任何可能对普通用户有用的消息都应该通过 ereport 传递。尽管如此,系统中仍然有足够的内部“不可能发生”错误检查,从而使 elog 仍然被广泛使用;对于那些消息,它因其简记而被首选。

有关编写良好错误消息的建议,请参见 Section 56.3

[16 ] 也就是说,当 ereport 调用到达时,值是当前值;辅助报告例程中的 errno 更改不会影响该值。如果你要明确在 errmsg 的参数列表中编写 strerror(errno) ,则并非如此;因此,请勿这样做。