SPI_execute

名前

SPI_execute -- コマンドを実行する

概要

int SPI_execute(const char * command, bool read_only, long count)

説明

SPI_executeは指定したSQLコマンドを、count行分実行します。 read_onlytrueの場合、そのコマンドは読み取りのみでなければなりませんが、多少のオーバーヘッドが削減されます。

この関数は接続済みのプロシージャからのみ呼び出し可能です。

countが0の場合、そのコマンドを、適用される全ての行に対して実行します。 countが0より多ければ、そのコマンドが実行される行数は制限されます (ほぼLIMITと似ています)。 例えば、

SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);

は、テーブルに挿入できる行は多くても5行のみです。

複数のコマンドを1つの文字列として渡すことができます。 しかし実行する前に文字列全体が解析され、実行計画が作成されるため、後のコマンドはこの文字列内の先のオブジェクトの生成に依存することはできません。 SPI_executeは最後に実行したコマンドの結果を返します。 count制限はそれぞれのコマンドに独立に適用されますが、ルールによって生成される隠れたコマンドには適用されません。

read_onlyfalseの場合、文字列内の各コマンドを実行する前にSPI_executeはコマンドカウンタを増分し、新しいスナップショットを作成します。 このスナップショットは、現在のトランザクション隔離レベルがSERIALIZABLEまたはREPEATABLE READの場合は変更されません。 しかし、READ COMMITTEDモードでは、このスナップショットは更新され、他のセッションで新しくコミットされたトランザクションの結果を各コマンドから参照できます。 これは、そのコマンドがデータベースを変更する場合、一貫性の維持に重要です。

read_onlytrueの場合は、SPI_executeはスナップショットもコマンドカウンタも更新しません。 さらに、普通のSELECTコマンドのみをコマンド文字列内に記述することができます。 このコマンドは、その前後の問い合わせによって事前に確立済みのスナップショットを使用して実行されます。 この実行モードは読み書きモードよりもコマンドごとのオーバーヘッドが省略される分多少高速です。 また、これにより本当に安定(stable)な関数を構築することができます。 つまり、連続した実行は全て同じスナップショットを使用しますので、結果は変わることがないということです。

一般的に、SPIを使用する1つの関数内で読み取りのみコマンドと読み書きコマンドを混在させることは勧めません。 読み取りのみの問い合わせでは、読み書き問い合わせでなされたデータベースの更新結果を参照しないいため、非常に混乱した動作に陥ることがあります。

(最後の)コマンドが実行した実際の行数は、SPI_processedグローバル変数に返されます。 関数の戻り値がSPI_OK_SELECTSPI_OK_INSERT_RETURNINGSPI_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関数に渡すことができる行記述子です。 tuptabcxtallocedfreeはSPI呼び出し元での使用を意図していない内部的なフィールドです。

SPI_finishは、現在のプロシージャで割り当てられたSPITupleTableをすべて解放します。 SPI_freetuptableを呼び出して解放する場合、特定の結果テーブルを早めに解放することができます。

引数

const char * command

実行するコマンドを含む文字列。

bool read_only

読み取りのみの実行の場合true

long count

処理される、あるいは返される行の最大数。

戻り値

コマンドの実行に成功した場合、以下のいずれかの(非負の)値が返されます。

SPI_OK_SELECT

SELECTSELECT 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

ルールによって(例えば、UPDATEINSERTになったような)あるコマンドが他の種類のコマンドに書き換えられた場合です。

エラーの場合、以下のいずれかの負の値が返されます。

SPI_ERROR_ARGUMENT

commandNULL、あるいはcountが0未満の場合。

SPI_ERROR_COPY

COPY TO stdoutあるいはCOPY FROM stdinが試行された場合。

SPI_ERROR_TRANSACTION

トランザクション操作を行うコマンド(BEGINCOMMITROLLBACKSAVEPOINTPREPARE TRANSACTIONCOMMIT PREPAREDROLLBACK PREPARED、およびこれらの亜種)が試行された場合。

SPI_ERROR_OPUNKNOWN

コマンド種類が不明な場合(起きてはなりません)。

SPI_ERROR_UNCONNECTED

未接続なプロシージャから呼び出された場合。

注意

関数SPI_executeSPI_execSPI_execute_planSPI_execpSPI_processedSPI_tuptableの両方を変更します(ポインタのみで、構造体の内容は変更しません)。 SPI_execやその関連する関数の結果テーブルを後の呼び出しでまたがってアクセスしたいのであれば、これら2つのグローバル変数を局所的なプロシージャ変数に保存してください。