44.2. 报告服务器里的错误

在服务器代码里生成的错误,警告以及日志信息应该用 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_AMBIGUOUS_FUNCTION),
         errmsg("function %s is not unique",
                func_signature_string(funcname, nargs,
                                      actual_arg_types)),
         errhint("Unable to choose a best candidate function. "
                 "You may need to add explicit typecasts.")));

这个例子演示了使用格式化代码把运行时数值嵌入一个消息文本的用法。 同样,还提供了一个可选的"暗示"信息。

ereport 可用的附属过程有:

还有一个老一些的 elog 函数,仍然在频繁使用。 一个 elog 调用

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

完全等效于

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

请注意 SQLSTATE 错误代码总是缺省的,并且消息字串并没有包含在国际化信息字典里。 因此,elog 应该只用于内部错误以及低层的调试日志。 任何普通用户感兴趣的消息都应该通过 ereport 生成。 当然,还有大量内部的"不可能发生"的错误检查使用 elog; 因为这些信息最好还是表示得简单些好。

书写好的错误消息的建议可以在 Section 44.3 找到。

Notes

[1]

也就是说,在到达 ereport 调用的时候当前的数值; 在附属报告过程里对 errno 的修改将不会影响他。 但是如果你在 errmsg 的参数列表里明确地写 strerror(errno), 这一点就不能保证了,因此,请不要这么做。