下記のコマンドは、PL/Tcl関数内からデータベースアクセスを行う時に使用できるコマンドです。
spi_exec
?-count n
? ?-array name
? command
?loop-body
?
文字列として与えられたSQL問い合わせを実行します。
コマンド内のエラーは、エラーの発生となります。
さもなければ、このspi_exec
の戻り値はコマンドによって処理(選択、挿入、更新、削除)された行数、または、コマンドがユーティリティ文の場合はゼロとなります。
さらに、コマンドがSELECT
文の場合、選択された列の値は以下のようにTclの変数に格納されます。
-count
オプションの値は、spi_exec
に対し、そのコマンドで処理する最大行数を指示します。
これにより、問い合わせをカーソルとして設定し、FETCH
を実行することと同じことができます。
n
コマンドがSELECT
文の場合、その結果得られた列の値は、列名にちなんだ名前のTcl変数に格納されます。
-array
オプションが付与された場合は、列の値は指定された名前の連想配列の要素に格納され、その配列のインデックスとして列名が使用されます。
加えて、結果内での現在の行番号(ゼロから数えます)が「.tupno
」という名前の配列要素に格納されます。ただし、その名前が結果内の列名として使われていない場合に限られます。
問い合わせ文が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
... $
というシンボルを使用して引数を参照してください。
問い合わせがパラメータを使用する場合、Tclのリストとしてパラメータの型名を指定する必要があります。
(パラメータを使用しない場合はn
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を返します。
(さもなければ、ゼロを返します。)
subtransaction
command
command
に含まれるTclスクリプトが、SQLサブトランザクション中で実行されます。
スクリプトがエラーを返すと、上位のTclコードにエラーを返す前に、そのサブトランザクションをロールバックします。
更なる詳細と使用例については43.9を参照してください。
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設定パラメータは、特定の重要度のメッセージをクライアントに報告するか、サーバのログに書き出すか、あるいはその両方かを制御します。
詳細については第19章および43.8を参照してください。