50.2. 在服务器中报告错误

服务器代码内产生的错误、警告和日志消息应该使用ereport或者更老的elog生成。这个函数的使用有些复杂,因此有必要做一些解释。

对于每一个消息都有两个必要的元素:一个严重性级别(从DEBUGPANIC)和一个主消息文本。此外还有一些可选元素,其中最常见的是一个遵守 SQL 规范中 SQLSTATE 习惯的错误标识符代码。ereport本身只是一个 shell 函数,它的存在主要是为了在语法习惯上让消息的产生更像 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.")));

这展示了使用格式代码把运行时值嵌入到一个消息文本中的方法,其中还提供了一个可选的"hint"消息。

如果严重级别是ERROR或更高,ereport 会中止用户定义函数的执行并且不会返回到调用者。如果严重级别低于 ERRORereport会正常返回。

ereport可用的辅助例程是:

Note: 在一个ereport调用中,最多可以使用一个errtableerrtablecolerrtableconstrainterrdatatype或者errdomainconstraint函数。这些函数存在是为了允许应用抽取与错误情况相关的数据库对象名,而不需要检查可能已被本地化的错误消息文本。这些函数应该被用在应用需要对其进行自动错误处理的错误报告中。从PostgreSQL 9.3 开始,完整的覆盖只为 SQLSTATE 类别 23 中的错误存在(完整性约束违背),但是在未来这些很可能会被扩展。

有一个还在大量使用的旧的函数elog。一个elog调用:

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

完全等效于:

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

注意 SQLSTATE 错误代码总是被给予默认值,并且消息字符串不受翻译限制。因此,elog应该只被用于内部错误和低层次的调试日志。任何普通用户感兴趣的消息应该通过ereport。不管怎样,在仍广泛使用elog的系统中,有足够多的内部"不可能发生"的错误检查,出于记号简洁的目的这更适合于那些消息。

有关编写好的错误消息的建议可见Section 50.3

Notes

[1]

也就是说,该值时到达ereport调用时的当前值,在辅助报告例程内errno的改变不会影响它。但如果你在errmsg的参数列表中显式地写了strerror(errno)则不是这样,因此不要那样做。