50.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,
                                      NIL, actual_arg_types)),
         errhint("Unable to choose a best candidate function. "
                 "You might need to add explicit typecasts.")));

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

如果严重性级别是ERROR或更高,那么ereport 退出用户定义函数的执行并且不返回给调用者。 如果严重性级别低于ERROR,那么ereport正常返回。

ereport可用的附属过程有:

注意: errtableerrtablecolerrtableconstrainterrdatatypeerrdomainconstraint 中最多只有一个函数应该用在一个ereport调用中。 这些函数的存在允许应用提取与没有检测潜在本地化错误消息文本的错误条件相关的数据库对象的名字。 这些函数应该用在应用希望自动错误处理的错误报告中。自PostgreSQL 9.3起, 完全覆盖只是为了SQLSTATE class 23中的错误而存在(违反完整约束), 但是有可能会在未来扩展。

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

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

完全等效于:

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

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

书写好的错误消息的建议可以在第 50.3 节找到。

备注

[1]

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