どのようにルールシステムが機能するかを理解するためには、ルールがどのように起動され、その入力と結果は何かを理解しなければなりません。
ルールシステムは問い合わせパーサとプランナの中間に位置します。 ルールシステムは、入力としてパーサの出力、単一の問い合わせツリー、および何らかの特別な情報を持つ問い合わせツリーでもあるユーザ定義の書き換えルールを取り、結果として0個以上の問い合わせツリーを生成します。 ルールシステムの入力と出力は常にパーサ自体でも生成することができるもので、参照する対象は基本的にSQL文として表現できるものです。
では問い合わせツリーとは何でしょうか。
それは、SQL文を構成する個々の部品を別々に記憶した、SQL文の内部表現です。
debug_print_parse
、debug_print_rewritten
、もしくはdebug_print_plan
設定パラメータを設定していれば、サーバログ内で問い合わせツリーを見ることができます。
ルールアクションもpg_rewrite
システムカタログ内に問い合わせツリーとして格納されています。
これはログ出力のように整形されていませんが、まったく同じ情報を持っています。
問い合わせツリーそのものを読むためにはある程度の経験が必要です。 ルールシステムを理解するためには問い合わせツリーのSQL表現で十分ですので、本章ではその読み方については説明しません。
本章の問い合わせツリーのSQL表現形式を読む時に必要なのは、問い合わせツリー構造の中に分解された、ある文の部品を識別できることです。 問い合わせツリーには以下の部品があります。
これはどのコマンド(SELECT
、INSERT
、UPDATE
、DELETE
)が構文解析ツリーを作ったかを示す単純な値です。
範囲テーブルは問い合わせで使われるリレーションのリストです。
SELECT
文ではこれはFROM
キーワードの後で与えられるリレーションになります。
範囲テーブルのそれぞれの項目はテーブルもしくはビューを識別し、問い合わせの別の部品ではどんな名前で呼び出されるかを示します。 問い合わせツリーでは範囲テーブルの項目は名前よりも番号で参照されることが多いため、ここではSQL文とは違い、重複する名前があるかということは問題になりません。 これはルールの範囲テーブルがマージされた後に起こる可能性があります。 本章の例ではその状況を含んでいません。
問い合わせの結果が格納されるリレーションを識別する範囲テーブルへのインデックスです。
SELECT
問い合わせは結果リレーションを持ちません。
(SELECT INTO
の場合は特別ですが、INSERT ... SELECT
が付いたCREATE TABLE
とほぼ同じですので、ここでは個別には説明しません。)
INSERT
、UPDATE
、DELETE
コマンドでは、結果リレーションは変更が有効になるテーブル(もしくはビュー)です。
目的リストは問い合わせの結果を定義する式のリストです。
SELECT
の場合、この式は問い合わせの最終結果を構築するものです。
これらはSELECT
とFROM
キーワードの間にある式に対応します
(*
は単にリレーションの全ての列名の省略です。
これはパーサによって個別の列に展開されますので、ルールシステムが見ることはありません)。
DELETE
コマンドは結果を返しませんので、通常の目的リストは必要ありません。
その代わり、プランナは空の目的リストに特別なCTID項目を追加し、エグゼキュータが削除すべき行を見つけられるようにします。
(CTIDは結果リレーションが通常のテーブルの場合に追加されます。
もしビューであれば41.2.4で述べるように、代わりに行全体の変数がルールシステムによって追加されます。)
INSERT
問い合わせでは、目的リストは結果リレーションへ入る新規の行を示します。
これはVALUES
句かINSERT ... SELECT
の中のSELECT
句の式です。
書き換え処理の最初のステップでは、元の問い合わせでは割り当てられず、デフォルト値となっている列の目的リストの項目を追加します。
残った列(値が与えられていない列、かつデフォルト値を持たない列)は全て、プランナによって定数NULL式で埋められます。
UPDATE
コマンドでは、目的リストは古いものを置き換えるべき新しい行を示します。
ルールシステムではコマンド内のSET column = expression
部分にある式だけを持っています。
プランナは、古い行から新しい行へ値をコピーする式を挿入することにより、抜けている列を処理します。
DELETE
の場合と同様、エグゼキュータが更新すべき行を見つけられるように、CTIDもしくは行全体の変数が追加されます。
目的リストの各項目は、定数値、範囲テーブル内のリレーション中の1つの列を指し示す変数、パラメータ等の式を保持するか、または、関数呼び出し、定数、変数、演算子などにより作られた式のツリーを保持します。
問い合わせの条件は目的リストの項目に含まれている式によく似た式です。
この式の結果は、最終的な結果の行を得るための(INSERT
、UPDATE
、DELETE
またはSELECT
)演算を実行すべきかどうかを示すブール値です。
それはSQL文の中のWHERE
句に対応します。
問い合わせの結合ツリーはFROM
句の構造を表します。
SELECT ... FROM a, b, c
のような単純な問い合わせでは、結合ツリーは単なるFROM
項目のリストです。
なぜならこれらはどんな順番で結合しても構わないためです。
しかしJOIN
式、特に外部結合が使われた場合は、その結合が示す順番通りに結合しなければいけません。
この場合結合ツリーはJOIN
式の構造を表します。
特定のJOIN
句と関連付けられた制約(ON
もしくはUSING
式からのもの)はこれらの結合ツリーノードに付加された条件として格納されます。
頂点レベルのWHERE
式を頂点レベルの結合ツリー項目に付加された条件として格納することも便利です。
ですから、結合ツリーはSELECT
のFROM
句とWHERE
句の両方を表しているわけです。
ORDER BY
句のような、問い合わせツリーのその他の部品は、ここでは取り上げません。
ルールシステムはルールを適用している時にそこで項目を入れ替えることもありますが、これはルールシステムの基本とはあまり関係しません。