SPI_execute — コマンドを実行する
int SPI_execute(const char *command, boolread_only, longcount)
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にはその結果が含まれます。
一部のユーティリティコマンド(COPY, CREATE TABLE AS)は行セットを返しません。
このためSPI_tuptableはNULLですが、SPI_processedの中で処理行数を返します。
SPITupleTable構造体は以下のように定義されています。
typedef struct
{
MemoryContext tuptabcxt; /* 結果テーブルのメモリコンテキスト */
uint64 alloced; /* 割り当て済みのvalsの数 */
uint64 free; /* 解放されたvalsの数 */
TupleDesc tupdesc; /* 行記述子 */
HeapTuple *vals; /* 行 */
} SPITupleTable;
valsが行へのポインタの配列です
(有効な項目数はSPI_processedで判明します)。
tupdescは行を扱うSPI関数に渡すことができる行記述子です。
tuptabcxt、alloced、freeはSPI呼び出し元での使用を意図していない内部的なフィールドです。
SPI_finishは、現在のプロシージャで割り当てられたSPITupleTableをすべて解放します。
SPI_freetuptableを呼び出して解放する場合、特定の結果テーブルを早めに解放することができます。
const char * command実行するコマンドを含む文字列。
bool read_only読み取りのみの実行の場合true。
long count返される行の最大数。無制限なら0。
コマンドの実行に成功した場合、以下のいずれかの(非負の)値が返されます。
SPI_OK_SELECTSELECT(SELECT INTOを除く)が実行された場合。
SPI_OK_SELINTOSELECT INTOが実行された場合。
SPI_OK_INSERTINSERTが実行された場合。
SPI_OK_DELETEDELETEが実行された場合。
SPI_OK_UPDATEUPDATEが実行された場合。
SPI_OK_INSERT_RETURNINGINSERT RETURNINGが実行された場合。
SPI_OK_DELETE_RETURNINGDELETE RETURNINGが実行された場合。
SPI_OK_UPDATE_RETURNINGUPDATE RETURNINGが実行された場合。
SPI_OK_UTILITYユーティリティコマンド(CREATE TABLEなど)が実行された場合。
SPI_OK_REWRITTENルールによって(例えば、UPDATEがINSERTになったような)あるコマンドが他の種類のコマンドに書き換えられた場合です。
エラーの場合、以下のいずれかの負の値が返されます。
SPI_ERROR_ARGUMENTcommandがNULL、あるいはcountが0未満の場合。
SPI_ERROR_COPYCOPY TO stdoutあるいはCOPY FROM stdinが試行された場合。
SPI_ERROR_TRANSACTIONトランザクション操作を行うコマンド(BEGIN、COMMIT、ROLLBACK、SAVEPOINT、PREPARE TRANSACTION、COMMIT PREPARED、ROLLBACK PREPARED、およびこれらの亜種)が試行された場合。
SPI_ERROR_OPUNKNOWNコマンド種類が不明な場合(起きてはなりません)。
SPI_ERROR_UNCONNECTED未接続なプロシージャから呼び出された場合。
SPI問い合わせ実行関数はすべてSPI_processedとSPI_tuptableの両方を変更します(ポインタのみで、構造体の内容は変更しません)。
SPI_execや他の問い合わせ実行関数の結果テーブルを後の呼び出しでまたがってアクセスしたいのであれば、これら2つのグローバル変数を局所的なプロシージャ変数に保存してください。