Chapter 8. Postgres のルールシステム

Table of Contents
問合せツリーについて
ビューとルールシステム
INSERT、 UPDATE および DELETE についてのルール
ルールとパーミッション
ルール対トリガ

本番で稼働するルールシステムは概念としては単純ですが、 実際に使ってみると、判りにくいところが少なからずあります。 これらいくつかの判りにくいところと、 Postgresのルールシステムにおける 基本的な理論についは [Stonebraker et al, ACM, 1990] に書かれています。

他のいくつかのデータベースシステムは能動的データベースルールを 定義しています。通常それらはストアドプロシージャとトリガで、 Postgres では関数とトリガとして 実装されています。

問合せ書き換えシステム(以降、"ルールシステム"と呼びます)は 内蔵プロシージャとトリガとは全く異なります。 ルールシステムはルールを考察して問合せを修正し、 修正した問合せを、実行のためオプティマイザに渡します。 これは非常に強力なため、問合せ言語プロシージャ、ビューあるいは バージョンなど多くのパターンで使用することが出来ます。 このルールシステムの能力は [Ong and Goh, 1990] だけでなく [Stonebraker et al, ACM, 1990] でも解説されています。

問合せツリーについて

どのようにルールシステムが機能するかを理解するためには まずルールがどのように起動されその入力と結果とは何かを 理解しなければなりません。

ルールシステムは問合せのパーサとオプティマイザの中間に位置します。 ルールシステムは、入力としてパーサの出力と単一の問合せツリーおよび pg_rewrite カタログから、何らかの特別な情報を 持つ問合せツリーでもある書き換えルールを取得し、結果としてゼロから 複数個の問合せツリーを生成します。 ルールシステムの入力と出力は常にパーサ自体でも生成すること が出来るもので、参照する対象は基本的に SQL 文による式です。

では問合せツリーとは何でしょうか。それは生成されたひとつ ひとつのパーツが別々にどこに記憶されるかの SQL 文の内部表現です。Postgres バックエンド をデバッグレベル 4 で起動し、対話型バックエンドインターフェイスを使って 問合せを入力することによって問合せツリーを見ることが出来ます。 pg_rewrite システムカタログ内のルール アクションは同時に、問合せツリーとして記憶されます。それらは デバッグの出力のようにフォーマットされてはいませんが全く同じ情報 を持っています。

問合せツリーを読むためには多少の経験が必要なので筆者がルール システムについての作業を始めたときは大変でした。 コーヒメーカの前に立っていてコップを目的リストに、お湯と コーヒー粉を範囲テーブルに、そしてすべての操作ボタンを 条件式だと思い浮かべたことを思い出します。 問合せツリーの SQL の式はルールシステムを 理解するのに充分ですからこのドキュメントではどのように問合せ ツリーを読むのかには触れません。それらの理解と慣例を例示する ようになるには将来出て来る書類にまかせます。

問合せツリーのパーツ

このドキュメントで問合せツリーのSQL 式を読む 場合には、問合せツリーの構造内にあって問合せ文が分解された パーツがどれであるか見極めることができる必要があります。 問合せツリーのパーツとは以下に記述するものです。

コマンドの形式

どのコマンド (SELECT、 INSERT、 UPDATE、 DELETE) が パースツリーを生成したかを示す単純な値です。

範囲テーブル

範囲テーブルは問合せの中で使われるリレーションのリストです。 SELECT 文では FROM キーワードの後に与えられるものが リレーションです。

それぞれの範囲テーブルの項目はテーブルまたはビューを特定 し、他の問合せによるパーツではどのような名前で呼ばれている のかを通知します。問合せツリーにおいて範囲テーブルは名前で はなくインデックスで参照されますので SQL 文の中と同様に重複した名前が存在しても構いません。 この状況はルールの範囲テーブルがマージされた後に起こること があります。このドキュメントであげている例ではそうはなりま せん。

結果のリレーション

問合せの結果がどこに行くのかのリレーションを特定する 範囲テーブルへのインデックスです。

通常 SELECT は結果のリレーションを持ちません。 SELECT INTO の特殊な場合は CREATE TABLE、INSERT ... SELECT の流れとほぼ同等なので、一緒に説明します。

INSERT、UPDATE および DELETE において結果のリレーション はどこで変更が有効となるかのテーブル(または ビュー!)です。

目的リスト

目的リストは問合せの結果を定義する式のリストで、SELECT の場合 式は、問合せの最終出力を組み立てたものです。 それらは SELECT と FROM キーワードの間の式です。 (* はリレーションの全ての属性名にたいする単なる省略形です。)

DELETE は何の結果ももたらしませんので目的リストを必要と しません。実際にはオプティマイザは空の目的リストに特殊な 項目を付け加えます。しかしこのことはルールシステムの後 に起こることなので後述することにします。ルールシステムに 関して言えば目的リストは空です。

INSERT では目的リストは結果のリレーションへ行く新規の行を 記述します。結果のリレーションで抜けているカラムは、 オプティマイザが定数 NULL 式を付け加えます。 これは VALUES 句における、または INSERT ... SELECT における SELECT 句からの式です。

UPDATE では以前の行を置き換える新規の行を記述します。ここで オプティマイザは抜けているカラムに前の行からの値を、新規の行に 入れる式を挿入します。それと同時に DELETE で行ったと同じ特殊 項目を付け加えます。それは問合わせの SET 属性 = 式 の部分から の式です。

目的リストのそれぞれの項目は、定数値のこともある式、 範囲テーブル内のリレーションのうちの一つの属性を指し示す変数、 関数呼び出しにより作られたパラメータあるいは式のツリー、定数、 変数、演算子などを持っています。

条件

問合せの条件は目的リストの項目に含まれているような式 です。この式の結果は (INSERT、 UPDATE、 DELETE または SELECT) 操作によって最終行が処理されたかどうかを示すブール値です。 それは SQL 文の中の WHERE 句です。

その他

ORDER BY 句のような問合せツリーのその他のパーツには ここでは取り上げません。ルールシステムはルールを適用 しているときにそこの場所で項目を入れ換えますが、これは ルールシステムの基本とはあまり関係しません。GROUP BY はビューの定義に出てきたときは特別なもので、別途に ドキュメント化されるべきです。