SPI_execute
は指定したSQLコマンドを、count行分実行します。
read_onlyがtrueの場合、そのコマンドは読み取りのみでなければなりませんが、多少のオーバーヘッドが削減されます。
この関数は接続済みのプロシージャからのみ呼び出し可能です。
countが0の場合、そのコマンドを、適用される全ての行に対して実行します。 countが0より多ければ、countを超えない数の行が取り出されます。 問い合わせにLIMIT句と追加するの同じように、countに達すれば、実行は止まります。 例えば、
SPI_execute("SELECT * FROM foo", true, 5);
は、テーブルから多くても5行しか取り出しません。 この制限はコマンドが実際に行を返した場合にのみ有効なことに注意して下さい。 例えば
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
は、countパラメータを無視して、barからすべての行を挿入します。 しかし、
SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
は、5番目のRETURNINGの結果行を取り出した後に実行が止まりますので、多くても5行を挿入するだけです。
複数のコマンドを1つの文字列として渡すことができます。
SPI_execute
は最後に実行したコマンドの結果を返します。
count制限は(最後の結果が返されただけだとしても)それぞれのコマンドに独立に適用されます。
この制限はルールによって生成される隠れたコマンドには適用されません。
read_onlyがfalseの場合、文字列内の各コマンドを実行する前にSPI_execute
はコマンドカウンタを増分し、新しいスナップショットを作成します。
このスナップショットは、現在のトランザクション隔離レベルがSERIALIZABLEまたはREPEATABLE READの場合は変更されません。
しかし、READ COMMITTEDモードでは、このスナップショットは更新され、他のセッションで新しくコミットされたトランザクションの結果を各コマンドから参照できます。
これは、そのコマンドがデータベースを変更する場合、一貫性の維持に重要です。
read_onlyがtrueの場合は、SPI_execute
はスナップショットもコマンドカウンタも更新しません。
さらに、普通のSELECTコマンドのみをコマンド文字列内に記述することができます。
このコマンドは、その前後の問い合わせによって事前に確立済みのスナップショットを使用して実行されます。
この実行モードは読み書きモードよりもコマンドごとのオーバーヘッドが省略される分多少高速です。
また、これにより本当に安定(stable)な関数を構築することができます。
つまり、連続した実行は全て同じスナップショットを使用しますので、結果は変わることがないということです。
一般的に、SPIを使用する1つの関数内で読み取りのみコマンドと読み書きコマンドを混在させることは勧めません。 読み取りのみの問い合わせでは、読み書き問い合わせでなされたデータベースの更新結果を参照しないいため、非常に混乱した動作に陥ることがあります。
(最後の)コマンドが実行した実際の行数は、SPI_processedグローバル変数に返されます。 関数の戻り値がSPI_OK_SELECT、SPI_OK_INSERT_RETURNING、SPI_OK_DELETE_RETURNING、またはSPI_OK_UPDATE_RETURNINGの場合、SPITupleTable *SPI_tuptableグローバルポインタを使用して、結果の行にアクセスすることができます。 また、一部のユーティリティコマンド(EXPLAINなど)は行セットを返しますが、この場合もSPI_tuptableにはその結果が含まれます。
SPITupleTable構造体は以下のように定義されています。
typedef struct { MemoryContext tuptabcxt; /* 結果テーブルのメモリコンテキスト */ uint32 alloced; /* 割り当て済みのvalsの数 */ uint32 free; /* 解放されたvalsの数 */ TupleDesc tupdesc; /* 行記述子 */ HeapTuple *vals; /* 行 */ } SPITupleTable;
valsが行へのポインタの配列です (有効な項目数はSPI_processedで判明します)。 tupdescは行を扱うSPI関数に渡すことができる行記述子です。 tuptabcxt、alloced、freeはSPI呼び出し元での使用を意図していない内部的なフィールドです。
SPI_finish
は、現在のプロシージャで割り当てられたSPITupleTableをすべて解放します。
SPI_freetuptable
を呼び出して解放する場合、特定の結果テーブルを早めに解放することができます。
コマンドの実行に成功した場合、以下のいずれかの(非負の)値が返されます。
SELECT(SELECT INTOを除く)が実行された場合。
SELECT INTOが実行された場合。
INSERTが実行された場合。
DELETEが実行された場合。
UPDATEが実行された場合。
INSERT RETURNINGが実行された場合。
DELETE RETURNINGが実行された場合。
UPDATE RETURNINGが実行された場合。
ユーティリティコマンド(CREATE TABLEなど)が実行された場合。
ルールによって(例えば、UPDATEがINSERTになったような)あるコマンドが他の種類のコマンドに書き換えられた場合です。
エラーの場合、以下のいずれかの負の値が返されます。
commandがNULL、あるいはcountが0未満の場合。
COPY TO stdoutあるいはCOPY FROM stdinが試行された場合。
トランザクション操作を行うコマンド(BEGIN、COMMIT、ROLLBACK、SAVEPOINT、PREPARE TRANSACTION、COMMIT PREPARED、ROLLBACK PREPARED、およびこれらの亜種)が試行された場合。
コマンド種類が不明な場合(起きてはなりません)。
未接続なプロシージャから呼び出された場合。