PostgreSQL 9.1.1文書
前のページ | 巻戻し |  | 早送り | 次のページ

# SPI_execute

## 名前

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

## 概要

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

## 説明

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

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

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

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

は、テーブルに挿入できる行は多くても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`を呼び出して解放する場合、特定の結果テーブルを早めに解放することができます。

## 引数

`const char * `command``

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

`bool `read_only``

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

`long `count``

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

## 戻り値

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

`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`

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

## 注意

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

前のページ | ホーム | 次のページ
SPI_pop | 上に戻る | SPI_exec