"CREATE RULE" SQL 11/05/95 日本語PostgreSQL 日本語PostgreSQL

名称

create rule - 新規のルールを定義します

形式

create rule rule_name
    as on event
      to object [where clause]
    do [instead]
    [action | nothing | [actions...]]
    

説明

create rule は新しいルールを定義するのに使います。

ここで、eventselect 、update 、delete 、insert の内のどれかになります。objectはクラス名もしくは、クラス.カラム(class.column)になります。 from 句、 where 句と、actionはそれぞれ通常の SQL の from 句、 where 句、そして、次のような違いのある SQL コマンド群です。

SQL の中でインスタンス変数が許される時にはいつでも new

もしくは current

をその代わりに使うことができます。

ルールのセマンティックでは、個々のインスタンスがアクセス、更新、挿入、削除をされた時に、 current

インスタンス(検索、更新、削除の時)と new

インスタンス(更新と追加の時)が存在します。もしイベントが on

句で指定されて、現在のインスタンスに対して where

句で指定された条件が真であれば、ルールのactionのパートが実行されます。しかしながらまず、現在のインスタンスまたあるいは新しいインスタンスのフィールド値は


current.attribute-name new.attribute-name
として置き換えられます。ルールのactionのパートは、動作するユーザコマンドと同様のコマンドとトランザクション識別子を使って実行します。

SQL ルールの注意箇所は順番です。もし同じクラス名やインスタンス変数がイベント、 where

句と、ルールのactionパートの中に現れると、すべて違うタプルの変数として扱われます。もっと正確に言えば、 new

current

はのみがこれらの句の中で共有することのできるタプル変数となります。例えば、次の2つのルールは同じセマンティックを持ちます:

on update to EMP.salary where EMP.name = Joe
	do update EMP ( ... ) where ...

on update to EMP-1.salary where EMP-2.name = Joe do update EMP-3 ( ... ) where ...
各々のルールはオプションのタグとして instead

を付けることができます。このタグが無ければ、ルールの条件パートにイベントが起こった時に、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
    

参照

rule(l) ,view(l) .

バグ

instead ルールは適切に動きません。

SQL ルールのオブジェクトは配列参照にはできません。またパラメータを持つこともできません。

"oid"フィールドは別として、システム属性はルールから参照することはできません。別のところでは、これは関数のインスタンス(例えば "foo(emp)" where "emp" はクラスです)はルールの中から呼び出すことができません。

ルールシステムはルール文と問い合わせプランをテキスト属性として保存します。これはルールを作るときにルールとそれに付随する内部表現が 1ページ (8KB) を越えると失敗することを意味します。