SPI_execute — 執行一條命令
int SPI_execute(const char *command
, boolread_only
, longcount
)
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
或 SPI_OK_MERGE_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;
欄位 tupdesc
、vals
和 numvals
可以由 SPI 呼叫者使用;其餘欄位是內部使用的。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_MERGE_RETURNING
如果執行了 MERGE RETURNING
SPI_OK_UTILITY
如果執行了實用命令(例如 CREATE TABLE
)
SPI_OK_REWRITTEN
如果命令被 規則重寫為另一種型別的命令(例如,UPDATE
變為 INSERT
)。
發生錯誤時,將返回以下負值之一
SPI_ERROR_ARGUMENT
如果 command
為 NULL
或 count
小於 0
SPI_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 函式變數中。
如果您在文件中發現任何不正確、與您對特定功能的經驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。