PostgreSQL SPI 中的错误处理

PostgreSQL SPI 用于在 C 或是其余编程语言编写的扩展函数(存储过程)中调用数据库自己的解析器、规划器和执行器的功能,以及对 SQL 语句进行执行。数据库

在最重要的一个函数 SPI_execute 的文档中,说明了发生错误时,将会返回下列负值之一:编程

SPI_ERROR_ARGUMENT 若是command为NULL或者count小于 0编程语言

SPI_ERROR_COPY 若是尝试COPY TO stdout或者COPY FROM stdin函数

SPI_ERROR_TRANSACTION 若是尝试了一个事务操纵命令( BEGIN、 COMMIT、 ROLLBACK、 SAVEPOINT、 PREPARE TRANSACTION、 COMMIT PREPARED、 ROLLBACK PREPARED或者其余变体)日志

SPI_ERROR_OPUNKNOWN 若是命令类型位置(不该该会发生)code

SPI_ERROR_UNCONNECTED 若是调用过程未链接事务

你必定会奇怪,为何只有这么几个呢?还有其余的不少状况呢?好比传进去的 SQL 有语法错误,或是实际执行时报错,这些状况下会返回什么呢?开发

而后文档中又说:注意若是一个经过 SPI 调用的命令失败,那么控制将不会返回到你的过程当中。固然啦,你的过程所在的事务或者子事务将被回滚(这可能看起来使人惊讶,由于据文档所说 SPI 函数大多数都有错误返回约定。可是那些约定只适用于在 SPI 函数自己内部检测到的错误)。经过在可能失败的 SPI 调用周围创建本身的子事务能够在错误以后恢复控制。当前文档中并未记载这些,由于所需的机制仍然在变化中。文档

原来检查 SPI_execute 的源代码可知,只有发生了上面几种状况的错误时,SPI 会返回给你错误代码;而其余更内部的地方发生的全部错误,程序都是直接调用的 ereport 方法,若是错误级别达到 ERROR 及以上时,会中断程序的执行,将事务回滚,并将错误信息:一、记到日志中;二、返回给客户端。it

所以,其余状况的错误,你根本就没必要处理,PG 也不给你机会处理。你只有在客户端才能看到具体的报错信息。

若是你是在一个很大的逻辑里,不想整个事务被回滚掉,想出错后控制还返回给程序,能够用 PG_TRYPG_CATCHPG_END_TRY 几个宏来通知 ereport 将控制返回给程序,同时用一个子事务把对 SPI 的调用包起来,参考 PL/Python 源代码 plpy_spi.c 中,PLy_spi_subtransaction_<begin/commit/abort> 等方法的处理。

这也是由于 PostgreSQL 是用 C 语言开发的,一个不够强的地方。假如未来用 Rust 重写,

相关文章
相关标签/搜索