PostgreSQLにおけるビューの実装PostgreSQLにおけるビューはルールシステムを使って実装されています。VIEW文があるとします。mytab;実際、これと、以下の2つのコマンドの間にはまったく違いがありません。VIEWコマンドによって内部的にまったく同じ処理が行われるからです。PostgreSQLシステムカタログのビューについての情報はテーブルの情報と同一なので、パーサにとってもテーブルとビューは同じものになるということです。これらは同じもの、つまり、リレーションです。これは現時点の重要課題です。SELECTルールはすべての問い合わせに対し最後に適用されます。それぞれは他と異なるセマンティックを持っていて構文解析ツリーを新規に生成せずに、そこにあるものを修正します。したがってSELECTルールが一番初めに評価されなければいけません。SELECTルールでは1つのアクションしか許されず、それはINSTEADである無条件のSELECTアクションでなければいけません。SELECTのルールは実質的にviewのルールのみに限定されます。このドキュメントの例として挙げているのは、ちょっとした演算をする2つの結合のビューと、次にこれらの機能を利用するいくつかのビューです。最終結果が何らかの魔法の機能によりあたかも実テーブルのように振る舞うビューになるように、始めの2つのビューの内の1つは、INSERT、UPDATE、DELETE操作に対するルールを後で追加することでカスタマイズされます。つの例を挙げるほうがおいでしょう。例として操作するデータベースの名前はal_bundyです。このような名前なのかはすぐにわかるでしょう。PL/pgSQLがインストールされている必要があります。関数の生成は以下のようにします。plpgsql;始めの2つのルールシステムの説明に必要な実際のテーブルは以下のものです。cmに変換するファクタ);読者のほとんどが靴を履くでしょうからこのデータは確かに使えるはずです。世の中には靴紐のいらない靴もありますが、それではアルの生活が成り立ちませんので無視することにします。ビューは次のようにして作られます。VIEWコマンドは、shoelaceリレーションと、問い合わせ範囲テーブルの中でshoelaceリレーションが参照されるときはいつでも、適用されるべき書き換えルールの存在を示す項目をpg_rewriteに作ります。ルールはルール条件(SELECTルールは現在持つことができませんので、非SELECTルールのところで取りあげられます)を持たないINSTEADです。ルールアクションは問い合わせ条件を持っています。ルールアクションはビュー生成コマンドのSELECT文とまったく同じ問い合わせツリーです。pg_rewrite項目のNEWとOLD(歴史的な理由により、出力用の問い合わせツリーではそれは*NEW*や*CURRENT*という名前が付いています)に対する2つの特別な範囲テーブル項目はSELECTルールには関係ありません。shoelace_dataにデータを入れます。アルはここで人生初のSELECTを入力します。rows)アルが行うビューに対する最も簡単なSELECTですので、これでビューの基本ルールを説明します。shoelaceはパーサによって処理され、次の構文解析ツリーが生成されます。shoelace;この操作はルールシステムに伝えられます。pg_rewriteに存在するか調べます。_RETshoelaceを見つけ出します。u.un_name);パーサが、演算と検索条件を適切な関数の呼び出しに変換したことに注目してください。実際は、これは何も変更しません。ビューを展開するために、システムでは単純にルールのアクション構文解析ツリーを持つ副問い合わせ範囲テーブルの項目を作り、ビューを参照していた元の範囲テーブルを置き換えます。書き換えられた結果の構文解析ツリーはアルが以下のように入力した場合とほぼおなじです。shoelace;しかし1つだけ違いがあります。*NEW*を持っていることです。これらの項目は副問い合わせの結合ツリーや目的リストに参照されないので、直接問い合わせでは使われません。書き換えシステムではそれらを、ビューを参照した範囲テーブルの項目にもともと存在したアクセス権限確認情報を格納するために使います。この方法で、書き換えられた問い合わせで直接ビューを使用していなくても、エクゼキュータはユーザがそのビューにアクセスするための正しい権限を持っているか確認します。これが最初に適用されるルールです。ルールシステムは始めの問い合わせ(この例ではそれ以上はありません)の残りの範囲テーブルの項目をチェックし続けます。ルールシステムは、追加された副問い合わせの項目がビューを参照するかを再帰的に確認します(しかし*OLD*や*NEW*は展開しません。なければ無限再帰になってしまいます!)。この例ではshoelace_dataやunitのための書き換えルールはありません。書き換えは完結し、上記がプランナに渡される最終的な結果となります。ここで、ブルースブラザーズが靴を買いにお店にやって来て、ブルースブラザーズですから、同じ靴を履きたいと言います。履きたいので靴紐も必要です。店に置いてある靴紐(の色とサイズ)に一致する靴がどれで、完全に一致するものの在庫が2組以上あるかどうかをアルは知らなければいけません。アルはデータベースに問い合わせることが必要です。rows)アルは靴についての専門家ですので、sh1型の靴が該当することがわかります(sl7の靴紐は茶色で、それに合う茶色の靴はブルースブラザーズの好みではありません)。今回のパーサの出力は以下の構文解析ツリーです。2);一番始めに適用されるルールはshoe_readyビュー用のもので構文解析ツリーにおける結果は以下のようになります。ルールは副問い合わせの範囲テーブルとして代用され、レベル3の最終問い合わせツリーへと導きます。2);プランナはこのツリーを2レベルの問い合わせツリーに縮めます。下のselectはバラバラに処理する必要がないので2つ目selectに"引っ張り上げ"られます。2つ目のセレクトは集約関数を持つため、頂点からは区別されます。それらを引っ張り上げてしまうと一番上のselectの動作を変えてしまうことになり、それはしたくありません。問い合わせツリーを縮めることは書き換えシステムが自分で意識する必要がありません。ルールシステムにおいて(他のルールは別ですが)ビュールールの再帰処理を中止する機構はありません。RULEにより手作業で、互いを選択し合うようなビュールールを設定することによりのみ可能ですから、さほど深刻な問題ではありません。VIEWでは起こり得ません。非SELECT文のビュールールこれまでのビュールールの説明では構文解析ツリーの2つの詳細について触れませんでした。それらは、コマンドタイプと結果リレーションです。実際、ビューのルールはこれらの情報を必要としません。SELECTと他のコマンドに対する構文解析ツリーの間には大きな違いはありません。それらは明らかに違うコマンドタイプを持っていて、今回は結果リレーションは結果がどこに行くのかを示す範囲テーブルの項目を指し示します。それ以外ではまったく同じです。aとbの属性を持つテーブルt1、t2に対する以下の2つの命令文の構文解析ツリーはほとんど同等です。t2.a;範囲テーブルにはテーブルt1とt2に対する項目があります。目的リストにはテーブルt2に対する範囲テーブル項目の属性bを指し示す1つの変数があります。条件式に両方の範囲テーブルの属性aの等価性が比較されます。これらの結合ツリーはt1とt2の単純な結合を表しています。結果として、両方の構文解析ツリーは似たような実行計画になります。それらは共に2つのテーブルの結合です。t1から抜けている列はプランナが目的リストに追加し、最終の構文解析ツリーは、以下のようになります。t2.a;結合を実行したエクゼキュータは、以下のコマンドの結果セットと全く同じ結果セットを作成します。t2.a;とはいってもUPDATEにはちょっとした問題があります。エクゼキュータは、結合が行う処理の結果が何を意味しているかに関与しません。エクゼキュータは単に結果となる行のセットを作成するだけです。1つはSELECTコマンドでもう1つはUPDATEコマンドですが、違いはエクゼキュータを呼び出す側で扱われることです。呼び出し側は(構文解析ツリーを見て)、これがUPDATEであるとわかっていて、この結果がテーブルt1に入らなければいけないことを知っています。どの行が新しい行によって置換されなければならないのでしょうか。この問題を解決するため、UPDATE文(DELETE文も)の目的リストに別の項目が付け加えられます。それは現在のタプルID(CTID)です。これはファイルのブロック番号とその行のブロック中の位置を持つシステム属性です。テーブルがわかっている場合、CTIDは元のt1行の更新を抽出するために使うことができます。CTIDを目的リストに追加した後は、問い合わせは以下のようになります。t2.a;では、PostgreSQLの別の詳細説明に入りましょう。TRANSACTION処理は速いのです。UPDATEでは、(CTIDを取り除いたあと)テーブルに新しい結果の行が挿入され、その行のタプルヘッダ内ではcmaxを指し示すCTIDとxmaxの項目が現在のコマンドカウンタと現在のトランザクションIDにセットされます。このようにして、古い行は隠されトランザクションがコミットされたあとにvacuumが実際に削除することができます。これらの詳細が全部理解できれば、どんなコマンドに対してもまったく同じようにしてビューのルールを簡単に適用することができます。そこには差異がありません。PostgreSQLにおけるビューの能力ここまでで、ビューの諸定義が元の構文解析ツリーにどのように関与するかを解説しました。第2の例では、1つのビューからの単純なSELECTによって、最終的に4つのテーブルを結合する構文解析ツリーが生成されました(単位(unit)は違った名前で2回使われます)。利点ビューをルールシステムとともに実装する利点は、プランナが、どのテーブルをスキャンすべきか、それらのテーブル間の関連性、ビューからの制約条件、元の問い合わせ条件、これらを1つのパースツリーに持っていることです。元の問い合わせがすでにビューに対する結合であるときも同様です。プランナはここでどれが問い合わせ処理の最適経路かを決定しなければなりません。情報が多ければ多いほど、プランナはよりよい決定を下すことができます。PostgreSQLに実装されているルールシステムはこれが現時点で、提供されているすべての情報であることを保証します。上で説明したような置換をしたあとに、結果リレーションが副問い合わせの範囲テーブル項目を指す問い合わせツリーができます。これでは使えませんので、書き換えシステムがそのようなものを見つけるとエラーを発生します。これを変えるためには非SELECT問い合わせの動作を変えるルールを定義することができます。それが次の節の論題になります。INSERT、UPDATE、DELETEについてのルール。