PL/Tcl 函数内的 Tcl 代码,或从 PL/Tcl 函数调用的 Tcl 代码,都可能引发错误:要么是执行了某个非法操作,要么是通过 Tcl 的error命令或 PL/Tcl 的elog命令主动生成错误。在 Tcl 中,可以使用catch命令捕获这类错误。如果错误没有被捕获,而是一路传播到 PL/Tcl 函数执行的顶层,那么它就会在调用该函数的查询中作为 SQL 错误报告出来。
反过来,在 PL/Tcl 的spi_exec、spi_prepare和spi_execp命令中发生的 SQL 错误会作为 Tcl 错误报告,因此也可以被 Tcl 的catch命令捕获。(这些 PL/Tcl 命令中的每一个都会在子事务中运行其 SQL 操作,该子事务在出错时会回滚,因此任何部分完成的操作都会自动清理掉。)同样地,如果某个错误在未被捕获的情况下传播到顶层,它又会重新变成 SQL 错误。
Tcl 提供了一个errorCode变量,它以便于 Tcl 程序解释的形式携带关于错误的附加信息。该变量的内容采用 Tcl 列表格式,第一个词标识报告该错误的子系统或库;其后的内容则由相应子系统或库自行定义。对于由 PL/Tcl 命令报告的数据库错误,第一个词是POSTGRES,第二个词是 PostgreSQL 版本号,后续内容则是字段名/字段值对,用来提供关于该错误的详细信息。字段SQLSTATE、condition和message总是会提供(前两个分别对应Appendix A中所示的错误代码和条件名称)。可能出现的字段包括 detail、hint、context、 schema、table、column、 datatype、constraint、 statement、cursor_position、 filename、lineno以及 funcname。
处理 PL/Tcl 的errorCode信息时,一种方便的办法是把它载入数组中,这样字段名就变成了数组下标。对应的代码可能如下所示:
if {[catch { spi_exec $sql_command }]} {
if {[lindex $::errorCode 0] == "POSTGRES"} {
array set errorArray $::errorCode
if {$errorArray(condition) == "undefined_table"} {
# deal with missing table
} else {
# deal with some other type of SQL error
}
}
}
(双冒号显式指定errorCode是一个全局变量。)
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。