SPI_execute — コマンドを実行する
int SPI_execute(const char *command
, boolread_only
, longcount
)
SPI_execute
は指定したSQLコマンドを、count
行分実行します。
read_only
がtrue
の場合、そのコマンドは読み取りのみでなければなりませんが、多少のオーバーヘッドが削減されます。
この関数は接続済みのC関数からのみ呼び出し可能です。
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 SPITupleTable { /* 公開メンバ */ TupleDesc tupdesc; /* タプル記述子 */ HeapTuple *vals; /* タプルの配列 */ uint64 numvals; /* 有効なタプルの数 */ /* 非公開メンバ、外部呼び出し側のためのものではない */ uint64 alloced; /* vals配列に割り当てられた長さ */ MemoryContext tuptabcxt; /* 結果テーブルのメモリコンテキスト */ slist_node next; /* 内部情報のためのリンク */ SubTransactionId subid; /* SPITupleTableが生成されたサブトランザクション */ } 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_INSERT_RETURNING
INSERT RETURNING
が実行された場合。
SPI_OK_DELETE_RETURNING
DELETE RETURNING
が実行された場合。
SPI_OK_UPDATE_RETURNING
UPDATE 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_exec
や他の問い合わせ実行関数の結果テーブルを後の呼び出しでまたがってアクセスしたいのであれば、これら2つのグローバル変数を局所的なプロシージャ変数に保存してください。