無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

41.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章 を参照してください。


powered by SEO.CUG.NET