# 54.2.报告服务器内的错误

服务器代码中生成的错误、警告和日志消息应使用电子报告,或是它的堂兄埃洛格.这个函数的使用非常复杂,需要一些解释。

每条消息都需要两个元素:严重性级别(从调试惊恐)和一条主要的短信。此外,还有一些可选元素,其中最常见的是遵循SQL规范的SQLSTATE约定的错误标识符代码。电子报告它本身只是一个shell宏,主要是为了语法上的方便,使消息生成看起来像是C源代码中的一个函数调用。唯一一个直接被电子报告是严重程度。主消息文本和任何可选消息元素都是通过调用辅助函数生成的,例如,在电子报告呼叫

一个典型的呼叫电子报告可能是这样的:

ereport(ERROR,
        errcode(ERRCODE_DIVISION_BY_ZERO),
        errmsg("division by zero"));

这将指定错误严重性级别错误(常规错误)。这个错误代码call使用中定义的宏指定SQLSTATE错误代码src/include/utils/errcode。H这个call提供主要消息文本。

您还会经常看到这种较旧的样式,在辅助函数调用周围有一组额外的括号:

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."));

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

如果严重性级别为错误或者更高,电子报告中止当前查询的执行,不返回调用方。如果严重程度低于错误, 电子报告恢复正常。

可用的辅助例程电子报告是:

  • errcode(sqlerrcode)指定条件的SQLSTATE错误标识符代码。如果未调用此例程,则错误标识符默认为ERRCODE_内部错误当错误严重性级别为错误或者更高,ERRCODE_警告当错误级别为警告,否则注意(及以下)ERRCODE_成功完成.虽然这些默认设置通常很方便,但在忽略这些设置之前,请始终考虑它们是否合适errcode()呼叫

  • errmsg(const char*msg,…)指定主要错误消息文本,以及可能要插入其中的运行时值。插入由把格式数据写成串-样式格式代码。除标准格式代码外把格式数据写成串,格式代码%m可用于插入返回的错误消息斯特雷罗对于当前值呃不. [16] %m不需要在参数列表中为。请注意,消息字符串将在gettext在处理格式代码之前进行可能的本地化。

  • errmsg_内部(常量字符*msg,…),但消息字符串不会被翻译或包含在国际化消息字典中。这应该用于“不可能发生”的情况,这些情况可能不值得花费翻译工作。

  • errmsg_复数形式(常量字符*fmt_单数,常量字符*fmt_复数,无符号长n,…)就像,但支持各种复数形式的信息。*fmt_单数是英文单数格式,fmt_复数形式是英语复数形式,n*是确定需要哪种复数形式的整数值,其余参数将根据选定的格式字符串进行格式化。有关更多信息,请参阅第55.2.2节.

  • errdetail(const char*msg,…)提供可选的“详细信息”消息;当有其他信息似乎不适合放在主消息中时,可以使用此选项。消息字符串的处理方式与.

  • errdetail_内部(const char*msg,…)错误细节,但消息字符串不会被翻译或包含在国际化消息字典中。这应该用于不值得花费翻译工作的细节信息,例如,因为它们太过技术化,对大多数用户都没有用处。

  • errdetail_复数(const char*fmt_单数,const char*fmt_复数,无符号长n,…)就像错误细节,但支持各种复数形式的信息。有关更多信息,请参阅第55.2.2节.

  • errdetail_log(const char*msg,…)错误细节除了这个字符串只会进入服务器日志,而不会进入客户端。如果两者都有错误细节(或上述等效物之一)和Erru日志然后一个字符串进入客户端,另一个进入日志。这对于安全性太高或太大而无法包含在发送给客户端的报告中的错误详细信息非常有用。

  • errdetail_log_复数(常量字符*fmt_单数,常量字符*fmt_复数,无符号长n,…)就像Erru日志,但支持各种复数形式的信息。有关更多信息,请参阅第55.2.2节.

  • errhint(const char*msg,…)提供可选的“提示”消息;这是在提供关于如何解决问题的建议时使用的,而不是关于出错原因的事实细节。消息字符串的处理方式与.

  • errhint_复数形式(常量字符*fmt_单数,常量字符*fmt_复数,无符号长n,…)就像错误提示,但支持各种复数形式的信息。有关更多信息,请参阅第55.2.2节.

  • errcontext(const char*msg,…)通常不会直接从电子报告信息网站;而是用在错误\u上下文\u堆栈回调函数,以提供有关发生错误的上下文的信息,例如PL函数中的当前位置。消息字符串的处理方式与.与其他辅助函数不同,它可以在每个电子报告呼叫这样提供的连续字符串用分隔的换行符连接起来。

  • 错误位置(int cursorpos)指定查询字符串中错误的文本位置。目前,它只适用于在查询处理的词汇和语法分析阶段检测到的错误。

  • errtable(关系rel)指定一个关系,其名称和架构名称应作为辅助字段包含在错误报告中。

  • errtablecol(关系rel,int attnum)指定一列,其名称、表名和架构名应作为辅助字段包含在错误报告中。

  • errtableconstraint(关系rel,const char*conname)指定一个表约束,其名称、表名和架构名应作为辅助字段包含在错误报告中。为此,索引应被视为约束,无论它们是否具有关联的pg_约束进入注意传递底层堆关系,而不是索引本身,因为雷尔.

  • errdatatype(Oid datatypeOid)指定一种数据类型,其名称和架构名称应作为辅助字段包含在错误报告中。

  • errdomainconstraint(Oid datatypeOid,const char*conname)指定一个域约束,其名称、域名和架构名称应作为辅助字段包含在错误报告中。

  • errcode_for_file_access()是一个方便的函数,用于为与文件访问相关的系统调用中的故障选择适当的SQLSTATE错误标识符。它使用保存的呃不以确定要生成的错误代码。通常情况下,这应该与%m在主错误消息文本中。

  • errcode_for_socket_access()是一个方便的函数,用于为套接字相关系统调用中的故障选择适当的SQLSTATE错误标识符。

  • errhidestmt(bool hide_stmt)可以调用以指定对声明:邮局主管日志中消息的一部分。通常,如果消息文本已经包含当前语句,则这是合适的。

  • errhidecontext(bool hide_ctx)可以调用以指定对背景:邮局主管日志中消息的一部分。这只应用于重复包含上下文会使日志过多的详细调试消息。

# 笔记

最多有一个功能犯错的, 埃拉泰科尔, 错误表约束, 错误数据类型errdomainconstraint应该用在电子报告呼叫这些函数允许应用程序提取与错误条件相关联的数据库对象的名称,而无需检查潜在的本地化错误消息文本。这些函数应该在错误报告中使用,因为应用程序可能希望自动处理错误。从PostgreSQL 9.3开始,只有SQLSTATE类23(完整性约束冲突)中的错误才有完整的覆盖范围,但这可能会在将来扩展。

还有一个更老的函数埃洛格这仍然被大量使用。一埃洛格电话:

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

完全等同于:

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

请注意,SQLSTATE错误代码始终是默认的,消息字符串不需要翻译。因此埃洛格应仅用于内部错误和低级调试日志记录。普通用户可能感兴趣的任何信息都应该通过电子报告.尽管如此,系统中有足够多的内部“不可能发生”错误检查埃洛格仍然被广泛使用;由于其符号的简单性,这些消息首选它。

有关编写正确错误消息的建议,请参见第54.3节.