SPI_execute

SPI_execute —执行命令

Synopsis

int SPI_execute(const char * command, bool read_only, long count)

Description

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在执行字符串中的每个命令之前,递增命令计数器并计算一个新的快照*。如果当前事务隔离级别为SERIALIZABLEREPEATABLE READ,则快照实际上不会更改,但是在READ COMMITTED模式下,快照更新允许每个命令从其他会话中查看新提交的事务的结果。这对于命令修改数据库时的一致行为至关重要。

当* read_only true时,SPI_execute既不更新快照也不更新命令计数器,它仅允许普通SELECT命令出现在命令字符串中。使用先前为周围查询构建的快照执行命令。由于消除了每个命令的开销,因此该执行模式比读/写模式要快一些。它还允许构建 true 的 stable *函数:由于连续执行都将使用相同的快照,因此结果不会发生变化。

使用 SPI 在一个函数中混合使用只读和读写命令通常是不明智的。这可能会导致非常混乱的行为,因为只读查询将看不到读写查询完成的任何数据库更新的结果。

已执行(最后一个)命令的实际行数在全局变量SPI_processed中返回。如果函数的返回值为SPI_OK_SELECTSPI_OK_INSERT_RETURNINGSPI_OK_DELETE_RETURNINGSPI_OK_UPDATE_RETURNING,则可以使用全局指针SPITupleTable *SPI_tuptable来访问结果行。一些 Util 命令(例如EXPLAIN)也会返回行集,在这些情况下SPI_tuptable也将包含结果。某些 Util 命令(COPYCREATE 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 函数。 tuptabcxtallocedfree是 SPI 调用程序不打算使用的内部字段。

SPI_finish释放当前 C 函数中分配的所有SPITupleTable。如果完成了特定的结果表,则可以调用SPI_freetuptable来释放它。

Arguments

  • const char * command

    • 包含要执行的命令的字符串
  • bool read_only

    • true用于只读执行
  • 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)
  • SPI_OK_REWRITTEN

    • 如果该命令被rule重写为另一种命令(例如UPDATE成为INSERT)。

错误时,将返回以下负值之一:

  • SPI_ERROR_ARGUMENT

    • 如果* command NULL count *小于 0
  • SPI_ERROR_COPY

    • 如果尝试了COPY TO stdoutCOPY FROM stdin
  • SPI_ERROR_TRANSACTION

    • 如果尝试了 Transaction 操作命令(BEGINCOMMITROLLBACKSAVEPOINTPREPARE TRANSACTIONCOMMIT PREPAREDROLLBACK PREPARED或其任何变体)
  • SPI_ERROR_OPUNKNOWN

    • 如果命令类型未知(不应发生)
  • SPI_ERROR_UNCONNECTED

    • 如果从未连接的 C 函数调用

Notes

所有 SPI 查询执行功能都设置SPI_processedSPI_tuptable(仅是指针,而不是结构的内容)。如果需要在以后的调用中访问SPI_execute的结果表或另一个查询执行函数,请将这两个全局变量保存到本地 C 函数变量中。