Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

54.2. 在服务器中报告错误 #

使用 ereport 或其旧形式 elog创建服务器代码中生成的错误、警告和日志消息。此函数的使用是复杂的,需要一些解释。

每条消息都需要两个必填元素:一个严重级别(范围从 DEBUGPANIC,定义在 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."));

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

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

ereport 的可用辅助例程是

注意

ereport 调用中最多只能使用以下函数之一:errtableerrtablecolerrtableconstrainterrdatatypeerrdomainconstraint。这些函数的存在是为了允许应用程序提取与错误状况关联的数据库对象名称,而无需检查可能已本地化的错误消息文本。这些函数应用于可能应用程序希望进行自动错误处理的错误报告。从 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),则不会产生上述情况;因此,请不要这样做。