# 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_processed
和SPI_tuptable
(只是指针,而不是结构的内容)。如果需要访问的结果表,将这两个全局变量保存到本地 C 函数变量中SPI_执行
或以后调用的另一个查询执行函数。