PL/Tclからのデータベースアクセス

PostgreSQL 9.1.1文書
前のページ | 巻戻し | 第 40章PL/Tcl - Tcl手続き言語 | 早送り | 次のページ

# 40.5. PL/Tclからのデータベースアクセス

下記のコマンドは、PL/Tcl関数内からデータベースアクセスを行う時に使用できるコマンドです。

``spi_exec` ?-count `n`? ?-array `name`? `command` ?`loop-body`?`

  文字列として与えられたSQL問い合わせを実行します。 コマンド内のエラーは、エラーの発生となります。 さもなければ、この`spi_exec`の戻り値はコマンドによって処理（選択、挿入、更新、削除）された行数、または、コマンドがユーティリティ文の場合はゼロとなります。 さらに、コマンドが`SELECT`文の場合、選択された列の値は以下のようにTclの変数に格納されます。

  `-count`オプションの値は、`spi_exec`に対し、そのコマンドで処理する最大行数を指示します。 これにより、問い合わせをカーソルとして設定し、`FETCH `n``を実行することと同じことができます。

  コマンドが`SELECT`文の場合、その結果得られた列の値は、列名にちなんだ名前のTcl変数に格納されます。 `-array`オプションが付与された場合は、列の値は指定した名前の連想配列に格納され、その配列のインデックスとして列名が使用されます。

  問い合わせ文が`SELECT`文、かつ、`loop-body`スクリプトが付与されなかった場合、結果のうち最初の行だけがTcl変数に格納されます。 他にも行があったとしても、それらは無視されます。 問い合わせが行を返さなかった場合は、変数への格納は発生しません （`spi_exec`の戻り値を検査することで、これを検出することができます）。 以下に例を示します。

      spi_exec "SELECT count(*) AS cnt FROM pg_proc"

  これは、`$cnt` Tcl変数を、`pg_proc`システムカタログの行数に設定します。

  `loop-body`オプション引数が付与された場合、それは、問い合わせの結果内の行それぞれに対して一度だけ実行される小さなTclスクリプトです （`loop-body`は`SELECT`以外の問い合わせで付与された場合は無視されます）。 処理中の行の列値は、各繰り返しの前にTcl変数に格納されます。 以下に例を示します。

      spi_exec -array C "SELECT * FROM pg_class" {
          elog DEBUG "have table $C(relname)"
      }

  これは、`pg_class`の各行に対してログメッセージを出力します。 この機能は他のTclの繰り返し構文でも同様に動作します。 特にループ本体内の`continue`と`break`は通常通り動作します。

  問い合わせの結果、列がNULLであった場合、対象となる変数は代入されずに、"未設定状態"になります。

`spi_prepare` `query` `typelist`

  後の実行のために問い合わせ計画の準備、保存を行います。 保存された計画は現在のセッションが終了するまで保持されます。

  問い合わせはパラメータ、つまり、計画が実際に実行される時に常に与えられる値用のプレースホルダを持つことができます。 問い合わせ文字列の中では、`$1` ... `$`n``というシンボルを使用して引数を参照してください。 問い合わせがパラメータを使用する場合、Tclのリストとしてパラメータの型名を指定する必要があります。 （パラメータを使用しない場合は`typelist`には空のリストを指定してください。）

  `spi_prepare`の戻り値は問い合わせIDです。 このIDは後に`spi_execp`を呼び出す時に使用されます。 使用例については`spi_execp`を参照してください。

``spi_execp` ?-count `n`? ?-array `name`? ?-nulls `string`? `queryid` ?`value-list`? ?`loop-body`?`

  `spi_prepare`により事前に準備された問い合わせを実行します。 `queryid`は`spi_prepare`により返されたIDです。 その問い合わせがパラメータを参照する場合、`value-list`を与える必要があります。 これは、そのパラメータの実際の値を持つTclのリストです。 このリストの長さは、事前に`spi_prepare`で指定した引数型のリストの長さと同じでなければなりません。 問い合わせにパラメータがない場合は、`value-list`を省略してください。

  `-nulls`オプションの値は、空白文字と`'n'`という文字からなる文字列で、`spi_execp`に対し、どの引数がNULL値かを示します。 指定された場合、その文字列の長さは`value-list`の長さと正確に一致していなければなりません。 指定されない場合は、すべてのパラメータの値は非NULLです。

  問い合わせとそのパラメータをどこで指定するのかという点を除き、`spi_execp`は`spi_exec`と同様に動作します。 `-count`、`-array`、`loop-body`オプションも、そして、結果の値も同じです。

  ここで、プリペアド計画を使用した、PL/Tcl関数の例を示します。

      CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$
          if {![ info exists GD(plan) ]} {
              # 最初の呼び出しでは保存する計画を準備します。
              set GD(plan) [ spi_prepare \
                  "SELECT count(*) AS cnt FROM t1 WHERE num >= \$1 AND num <= \$2" \
                  [ list int4 int4 ] ]
          }
          spi_execp -count 1 $GD(plan) [ list $1 $2 ]
          return $cnt
      $$ LANGUAGE pltcl;

  `spi_prepare`に与える問い合わせ文字列の内側では、`$`n``記号が確実にそのまま`spi_prepare`に渡され、Tcl変数の代入による置き換えが起こらないようにバックスラッシュが必要です。

`spi_lastoid`

  直前の`spi_exec`または`spi_execp`によるコマンドが単一行の`INSERT`文であり、かつ、更新されるテーブルがOIDを持つ場合、そのコマンドによって挿入された行のOIDを返します。 （さもなければ、ゼロを返します。）

`quote` `string`

  指定された文字列内のすべての単一引用符とバックスラッシュ文字を二重化します。 `spi_exec`や`spi_prepare`で与えられたSQL問い合わせに挿入される予定の文字列を安全に引用符付けするために、これを使用することができます。 例えば、以下のような問い合わせ文字列を考えます。

      "SELECT '$val' AS ret"

  ここで、`val` Tcl変数に`doesn't`が実際に含まれているものとします。 これは最終的に以下の問い合わせ文字列になってしまいます。

      SELECT 'doesn't' AS ret

  これでは、`spi_exec`または`spi_prepare`の実行中に解析エラーが発生してしまいます。 正しく稼動させるには、実行したい問い合わせは以下のようにしなければなりません。

      SELECT 'doesn''t' AS ret

  これは、PL/Tclでは以下により形成することができます。

      "SELECT '[ quote $val ]' AS ret"

  `spi_execp`の持つ1つの利点は、パラメータはSQL問い合わせ文字列の一部として解析されることがありませんので、このようにパラメータの値を引用符付けする必要がないことです。

`elog` `level` `msg`

  ログまたはエラーメッセージを発行します。 使用できるレベルは、`DEBUG`、`LOG`、`INFO`、`NOTICE`、`WARNING`、`ERROR`、および`FATAL`です。 `ERROR`はエラー状態を発生します。 その上位レベルのTclコードで例外が捕捉されなければ、このエラーは問い合わせ呼び出し処理の外部へ伝播され、その結果、現在のトランザクションもしくはサブトランザクションはアボートされます。 これは実質的にTclの`error`コマンドと同一です。 `FATAL`はトランザクションをアボートし、現在のセッションを停止させます。 （PL/Tcl関数においてこのエラーレベルを使用すべき理由はおそらく存在しませんが、完全性のために用意されています。） 他のレベルは、異なる重要度のメッセージを生成するだけです。 log_min_messagesとclient_min_messages設定パラメータは、特定の重要度のメッセージをクライアントに報告するか、サーバのログに書き出すか、あるいはその両方かを制御します。 詳細については第18章を参照してください。

前のページ | ホーム | 次のページ
PL/Tclにおけるグローバルデータ | 上に戻る | PL/Tclのトリガプロシージャ