On this page
SPI_execute
SPI_execute —执行命令
Synopsis
int SPI_execute(const char * command, bool read_only, long count)
Description
SPI_execute对* count 行执行指定的 SQL 命令。如果 read_only *是true,则该命令必须是只读的,并且执行开销会有所减少。
该函数只能从连接的过程中调用。
如果* 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命令出现在命令字符串中。使用先前为周围查询构建的快照执行命令。由于消除了每个命令的开销,因此该执行模式比读/写模式要快一些。它还允许构建 true 的 stable *函数:由于连续执行都将使用相同的快照,因此结果不会发生变化。
使用 SPI 在一个函数中混合使用只读和读写命令通常是不明智的。这可能会导致非常混乱的行为,因为只读查询将看不到读写查询完成的任何数据库更新的结果。
已执行(最后一个)命令的实际行数在全局变量SPI_processed中返回。如果函数的返回值为SPI_OK_SELECT,SPI_OK_INSERT_RETURNING,SPI_OK_DELETE_RETURNING或SPI_OK_UPDATE_RETURNING,则可以使用全局指针SPITupleTable *SPI_tuptable来访问结果行。一些 Util 命令(例如EXPLAIN)也会返回行集,在这些情况下SPI_tuptable也将包含结果。某些 Util 命令(COPY,CREATE TABLE AS)不返回行集,因此SPI_tuptable为 NULL,但它们仍返回SPI_processed中处理的行数。
因此定义结构SPITupleTable:
typedef struct
{
MemoryContext tuptabcxt; /* memory context of result table */
uint64 alloced; /* number of alloced vals */
uint64 free; /* number of free vals */
TupleDesc tupdesc; /* row descriptor */
HeapTuple *vals; /* rows */
} SPITupleTable;
vals是指向行的指针的数组。 (有效条目的数量由SPI_processed给出.)tupdesc是行 Descriptors,您可以将其传递给处理行的 SPI 函数。 tuptabcxt,alloced和free是 SPI 调用程序不打算使用的内部字段。
SPI_finish释放当前过程中分配的所有SPITupleTable。如果完成了特定的结果表,则可以调用SPI_freetuptable来释放它。
Arguments
const char * command- 包含要执行的命令的字符串
bool read_onlytrue用于只读执行
long count- 要返回的最大行数,或
0无限制
- 要返回的最大行数,或
Return Value
如果命令执行成功,则将返回以下(负值)值之一:
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_INSERT_RETURNING- 如果执行了
INSERT RETURNING
- 如果执行了
SPI_OK_DELETE_RETURNING- 如果执行了
DELETE RETURNING
- 如果执行了
SPI_OK_UPDATE_RETURNING- 如果执行了
UPDATE RETURNING
- 如果执行了
SPI_OK_UTILITY- 如果执行了 Util 命令(例如
CREATE TABLE)
- 如果执行了 Util 命令(例如
SPI_OK_REWRITTEN- 如果该命令被rule重写为另一种命令(例如
UPDATE成为INSERT)。
- 如果该命令被rule重写为另一种命令(例如
错误时,将返回以下负值之一:
SPI_ERROR_ARGUMENT- 如果*
command为NULL或count*小于 0
- 如果*
SPI_ERROR_COPY- 如果尝试了
COPY TO stdout或COPY FROM stdin
- 如果尝试了
SPI_ERROR_TRANSACTION- 如果尝试了 Transaction 操作命令(
BEGIN,COMMIT,ROLLBACK,SAVEPOINT,PREPARE TRANSACTION,COMMIT PREPARED,ROLLBACK PREPARED或其任何变体)
- 如果尝试了 Transaction 操作命令(
SPI_ERROR_OPUNKNOWN- 如果命令类型未知(不应发生)
SPI_ERROR_UNCONNECTED- 如果从未连接的过程调用
Notes
所有 SPI 查询执行功能都设置SPI_processed和SPI_tuptable(仅是指针,而不是结构的内容)。如果需要在以后的调用中访问SPI_execute的结果表或另一个查询执行函数,请将这两个全局变量保存到本地过程变量中。