create rule - 新規のルールを定義します
create rule rule_name
as on event
to object [where clause]
do [instead]
[action | nothing | [actions...]]
create rule は新しいルールを定義するのに使います。
ここで、eventはselect 、update 、delete 、insert の内のどれかになります。objectはクラス名もしくは、クラス.カラム(class.column)になります。 from 句、 where 句と、actionはそれぞれ通常の SQL の from 句、 where 句、そして、次のような違いのある SQL コマンド群です。
もしくは current
をその代わりに使うことができます。
ルールのセマンティックでは、個々のインスタンスがアクセス、更新、挿入、削除をされた時に、 current
インスタンス(検索、更新、削除の時)と new
インスタンス(更新と追加の時)が存在します。もしイベントが on
句で指定されて、現在のインスタンスに対して where
句で指定された条件が真であれば、ルールのactionのパートが実行されます。しかしながらまず、現在のインスタンスまたあるいは新しいインスタンスのフィールド値は
として置き換えられます。ルールのactionのパートは、動作するユーザコマンドと同様のコマンドとトランザクション識別子を使って実行します。
current.attribute-name new.attribute-name
SQL ルールの注意箇所は順番です。もし同じクラス名やインスタンス変数がイベント、 where
句と、ルールのactionパートの中に現れると、すべて違うタプルの変数として扱われます。もっと正確に言えば、 new
と current
はのみがこれらの句の中で共有することのできるタプル変数となります。例えば、次の2つのルールは同じセマンティックを持ちます:
on update to EMP.salary where EMP.name = Joe do update EMP ( ... ) where ...各々のルールはオプションのタグとして instead
on update to EMP-1.salary where EMP-2.name = Joe do update EMP-3 ( ... ) where ...
を付けることができます。このタグが無ければ、ルールの条件パートにイベントが起こった時に、actionはユーザコマンドに追加する形で実行されます。他方では、actionパートはユーザコマンドの代わりに実行されます。後者のケースでは、アクションはキーワード nothing
とすることができます。
あるルールアプリケーションのためにリライトとインスタンスルールシステムのどちらかを選ぶ時に、リライトシステムでは current
はリレーションと制限句を参照し、インスタンスシステムではインスタンス(タプル)を参照することを覚えておいてください。
リライト
ルールシステムでは循環ルールを発見あるいは処理できまないことに注意することは重要です。例えば、次の2つのルール定義はそれぞれ Postgres に受け入れられますが、検索コマンドは Postgres をクラッシュさせます:
-- -- 循環リライトルールの組合せの例 -- create rule bad_rule_combination_1 is on select to EMP do instead select to TOYEMP
create rule bad_rule_combination_2 is on select to TOYEMP do instead select to EMP
-- -- この EMP からの検索の試行は Postgres をクラッシュさせます -- select * from EMP
ルールを定義するには、ルール定義権限(rule definition)を持ってなくてはなりません。(acl(l) を参照してください。)
--
-- Sam の給料を Joe と同じに調整します
--
create rule example_1 is
on update EMP.salary where current.name = Joe
do update EMP (salary = new.salary)
where EMP.name = Sam
Joe が給料の調整を受け取った時、イベントが真になり、Joe の現在のインスタンスと提案された新規インスタンスが実行ルーチンに提供されます。ですから、彼の新しい給料はその後に実行されるルールのactionパートに渡されます。これは Joe の給料を Sam に伝えます。
--
-- Joe の給料にアクセスされた時に Bill が受け取るようにします
--
create rule example_2 is
on select to EMP.salary
where current.name = Bill
do instead
select (EMP.salary) from EMP where EMP.name = Joe
--
-- Joe が 靴売場の従業員の給料にアクセスすることを禁止します
-- (pg_username() は現在のユーザ名を返します)
--
create rule example_3 is
on select to EMP.salary
where current.dept = shoe
and pg_username() = Joe
do instead nothing
-- -- 玩具売場で働く従業員の VIEW表を作ります -- create TOYEMP(name = char16, salary = int4)
create rule example_4 is on select to TOYEMP do instead select (EMP.name, EMP.salary) from EMP where EMP.dept = toy
--
-- 新人従業員はすべて 5,000 以下の給料とします
--
create rule example_5 is
on insert to EMP where new.salary > 5000
do update newset salary = 5000
instead ルールは適切に動きません。
SQL ルールのオブジェクトは配列参照にはできません。またパラメータを持つこともできません。
"oid"フィールドは別として、システム属性はルールから参照することはできません。別のところでは、これは関数のインスタンス(例えば "foo(emp)" where "emp" はクラスです)はルールの中から呼び出すことができません。
ルールシステムはルール文と問い合わせプランをテキスト属性として保存します。これはルールを作るときにルールとそれに付随する内部表現が 1ページ (8KB) を越えると失敗することを意味します。