# SPI_执行

SPI_执行——执行一个命令

# 概要

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

# 描述

SPI_执行执行指定的 SQL 命令*数数行。如果只读*是真的,该命令必须是只读的,并且执行开销有所减少。

此函数只能从连接的 C 函数调用。

如果*数数为零,则对它适用的所有行执行该命令。如果数数大于零,则不大于数数*将检索行;达到计数时停止执行,就像添加一个限制查询的子句。例如,

SPI_execute("SELECT * FROM foo", true, 5);

将从表中检索最多 5 行。请注意,这种限制仅在命令实际返回行时才有效。例如,

SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);

插入所有行酒吧, 忽略*数数*范围。然而,随着

SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);

最多插入 5 行,因为执行将在第五行之后停止返回结果行被检索。

您可以在一个字符串中传递多个命令;SPI_执行返回最后执行的命令的结果。这*数数*限制分别适用于每个命令(即使实际上只返回最后一个结果)。该限制不适用于规则生成的任何隐藏命令。

什么时候*只读错误的,SPI_执行增加命令计数器并计算一个新的快照*在执行字符串中的每个命令之前。如果当前事务隔离级别为可序列化或者可重复阅读, 但在阅读已提交快照更新模式允许每个命令查看来自其他会话的新提交事务的结果。当命令修改数据库时,这对于一致的行为至关重要。

什么时候*只读真的,SPI_执行不更新快照或命令计数器,它只允许普通选择命令出现在命令字符串中。使用先前为周围查询建立的快照执行命令。由于消除了每个命令的开销,这种执行模式比读/写模式要快一些。它也允许真正稳定的*要构建的函数:由于连续执行都将使用相同的快照,因此结果不会发生变化。

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

执行(最后)命令的实际行数在全局变量中返回SPI_processed.如果函数的返回值为SPI_OK_SELECT,SPI_OK_INSERT_RETURNING,SPI_OK_DELETE_RETURNING, 或者SPI_OK_UPDATE_RETURNING,那么就可以使用全局指针SPITupleTable *SPI_tuptable访问结果行。一些实用程序命令(例如解释) 还返回行集,并且SPI_tuptable在这些情况下也将包含结果。一些实用程序命令(复制,创建表为) 不返回行集,所以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;

田野tupdesc,瓦尔斯, 和数值可由 SPI 调用者使用;其余字段是内部的。瓦尔斯是一个指向行的指针数组。行数由下式给出数值(出于某种历史原因,此计数也返回SPI_processed)。tupdesc是一个行描述符,您可以将其传递给处理行的 SPI 函数。

SPI_完成释放所有人SPITupleTable在当前 C 函数期间分配的 s。您可以通过调用提前释放特定的结果表,如果您完成了它,请调用SPI_freetuptable.

# 论据

常量字符 * *命令*

包含要执行的命令的字符串

布尔 *只读*

真的用于只读执行

长 *数数*

要返回的最大行数,或0无限制

# 返回值

如果命令执行成功,则将返回以下(非负)值之一:

SPI_OK_SELECT

如果一个选择(但不是选择进入) 被执行

SPI_OK_SELINTO

如果一个选择进入被处决

SPI_OK_INSERT

如果插入被处决

SPI_OK_DELETE

如果一个删除被处决

SPI_OK_UPDATE

如果更新被处决

SPI_OK_INSERT_RETURNING

如果插入返回被处决

SPI_OK_DELETE_RETURNING

如果一个删除返回被处决

SPI_OK_UPDATE_RETURNING

如果更新返回被处决

SPI_OK_UTILITY

如果一个实用程序命令(例如,创建表) 被执行

SPI_OK_REWRITTEN

如果命令被重写为另一种命令(例如,更新变成了一个插入) 由一个规则.

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

SPI_ERROR_ARGUMENT

如果*命令空值要么数数*小于 0

SPI_ERROR_COPY

如果复制到标准输出要么从标准输入复制已尝试

SPI_ERROR_TRANSACTION

如果尝试了事务操作命令(开始,犯罪,回滚,保存点,准备交易,提交准备,已准备好回滚, 或其任何变体)

SPI_ERROR_OPUNKNOWN

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

SPI_ERROR_UNCONNECTED

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

# 笔记

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