SPI_execute
SPI_execute — 执行命令
语法
int SPI_execute(const char * command, bool read_only, long count)
描述
SPI_execute
为*count
行执行指定的 SQL 命令。如果read_only
*为true
,则命令必须是只读的,并且执行开销会略微降低。
此函数只能从已连接的 C 函数调用。
如果*count
为零,则对适用的所有行执行该命令。如果count
大于零,则最多检索count
*行;当达到计数时,执行停止,这很像向查询添加LIMIT
子句。例如,
SPI_execute("SELECT * FROM foo", true, 5);
将从表中检索最多 5 行。请注意,此类限制仅在命令实际返回行时才有效。例如,
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
插入bar
中的所有行,忽略*count
*参数。但是,使用
SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
最多插入 5 行,因为在检索到第五个RETURNING
结果行后执行将停止。
可以在一个字符串中传递多个命令;SPI_execute
返回最后执行的命令的结果。*count
*限制分别适用于每个命令(即使实际上只返回最后一个结果)。该限制不适用于规则生成的任何隐藏命令。
当*read_only
为false
时,SPI_execute
会增加命令计数器并在执行字符串中的每个命令之前计算一个新的快照*。如果当前事务隔离级别为SERIALIZABLE
或REPEATABLE READ
,则快照实际上不会更改,但在READ COMMITTED
模式下,快照更新允许每个命令看到来自其他会话的新提交事务的结果。当命令修改数据库时,这对于一致的行为至关重要。
当*read_only
为true
时,SPI_execute
不会更新快照或命令计数器,并且只允许在命令字符串中出现纯SELECT
命令。使用为周围查询先前建立的快照执行命令。由于消除了每个命令的开销,这种执行模式比读/写模式快一些。它还允许构建真正的稳定*函数:由于连续执行都将使用相同的快照,因此结果不会改变。
通常不建议在使用 SPI 的单个函数中混合只读和读写命令;这可能会导致非常混乱的行为,因为只读查询不会看到读写查询所做的任何数据库更新的结果。
(最后一个)命令执行的行数实际数量在全局变量SPI_processed
中返回。如果函数的返回值是SPI_OK_SELECT
、SPI_OK_INSERT_RETURNING
、SPI_OK_DELETE_RETURNING
或SPI_OK_UPDATE_RETURNING
,则可以使用全局指针SPITupleTable *SPI_tuptable
访问结果行。一些实用命令(如EXPLAIN
)也返回行集,并且SPI_tuptable
也将在这些情况下包含结果。一些实用命令(COPY
、CREATE TABLE AS
)不返回行集,因此SPI_tuptable
为 NULL,但它们仍会返回SPI_processed
中处理的行数。
结构SPITupleTable
因此定义
typedef struct SPITupleTable
{
/* Public members */
TupleDesc tupdesc; /* tuple descriptor */
HeapTuple *vals; /* array of tuples */
uint64 numvals; /* number of valid tuples */
/* Private members, not intended for external callers */
uint64 alloced; /* allocated length of vals array */
MemoryContext tuptabcxt; /* memory context of result table */
slist_node next; /* link for internal bookkeeping */
SubTransactionId subid; /* subxact in which tuptable was created */
} SPITupleTable;
SPI 调用方可以使用字段tupdesc
、vals
和numvals
;其余字段是内部字段。vals
是指向行的指针数组。行数由numvals
给出(出于历史原因,此计数也会在SPI_processed
中返回)。tupdesc
是行描述符,可以传递给处理行的 SPI 函数。
SPI_finish
释放当前 C 函数期间分配的所有SPITupleTable
。如果已完成特定结果表,可以通过调用SPI_freetuptable
提前释放该表。
参数
const char *
command
包含要执行的命令的字符串
bool
read_only
true
表示只读执行long
count
要返回的最大行数,或
0
表示无限制
返回值
如果命令执行成功,则将返回以下(非负)值之一
SPI_OK_SELECT
如果执行了
SELECT
(但不是SELECT INTO
)SPI_OK_SELINTO
如果执行了
SELECT INTO
SPI_OK_INSERT
如果执行了
INSERT
SPI_OK_DELETE
如果执行了
DELETE
SPI_OK_UPDATE
如果执行了
UPDATE
SPI_OK_MERGE
如果执行了
MERGE
SPI_OK_INSERT_RETURNING
如果执行了
INSERT RETURNING
SPI_OK_DELETE_RETURNING
如果执行了
DELETE RETURNING
SPI_OK_UPDATE_RETURNING
如果执行了
UPDATE RETURNING
SPI_OK_UTILITY
如果执行了实用程序命令(例如,
CREATE TABLE
)SPI_OK_REWRITTEN
如果命令被 规则 重写为另一种类型的命令(例如,
UPDATE
变成INSERT
)。
如果出错,则返回以下负值之一
SPI_ERROR_ARGUMENT
如果
command
为NULL
或count
小于 0SPI_ERROR_COPY
如果尝试了
COPY TO stdout
或COPY FROM stdin
SPI_ERROR_TRANSACTION
如果尝试了事务操作命令(
BEGIN
、COMMIT
、ROLLBACK
、SAVEPOINT
、PREPARE TRANSACTION
、COMMIT PREPARED
、ROLLBACK PREPARED
或其任何变体)SPI_ERROR_OPUNKNOWN
如果命令类型未知(不应该发生)
SPI_ERROR_UNCONNECTED
如果从未连接的 C 函数调用
备注
所有 SPI 查询执行函数都设置SPI_processed
和SPI_tuptable
(仅指针,不设置结构的内容)。如果您需要在后续调用中访问SPI_execute
或其他查询执行函数的结果表,请将这两个全局变量保存到本地 C 函数变量中。