[pgsql-jp: 38168] RULE〜ON INSERT と serial 型

Kawasaki Yusuke u-suke @ kawa.net
2007年 3月 18日 (日) 01:01:14 JST


川崎です。こんにちは。

RULE〜ON INSERT 時の serial 型の動作について、教えて下さい。
以下のような2つのテーブルがある構成で、src テーブルの id・val の値を
リアルタイムに dst テーブルに反映していきたいとします。

CREATE TABLE src ( id serial, val text );
CREATE TABLE dst ( id serial, val text );

実際には、コピー以外の操作もあるので、ビューでは実現できません。
具体的には、src に INSERT されれば、その id・val を dst にも INSERT して、
src が UPDATE されれば、dst でも同じ id の val を UPDATE して、
src から DELETE されれば、dst でも同じ id のレコードを DELETE します。
これを実現するため、以下の3つのルールを定義しました。

CREATE OR REPLACE RULE rule_src2dst_ins AS ON INSERT TO src
    DO INSERT INTO dst VALUES ( NEW.id, NEW.val );
CREATE OR REPLACE RULE rule_src2dst_upd AS ON UPDATE TO src
    DO UPDATE dst SET val = NEW.val WHERE dst.id = NEW.id;
CREATE OR REPLACE RULE rule_src2dst_del AS ON DELETE TO src
    DO DELETE FROM dst WHERE dst.id = OLD.id;

ON UPDATE と ON DELETE のルールは期待通り動作しているように見えます。
しかし INSERT 時は、src_id_seq のシーケンスが1つカウントアップして、
dst 側の id には src 側の id+1 の値が入ってしまします。

hoge=# INSERT INTO src ( val ) VALUES ( 'HELLO' );
hoge=# SELECT * FROM src;
 id |  val
----+-------
  1 | HELLO
hoge=# SELECT * FROM dst;
 id |  val
----+-------
  2 | HELLO    ← id=1 でなくて id=2 になってる
hoge=# SELECT currval('src_id_seq');
 currval
---------
       2      ← 1 でなくて 2 にカウントアップしている

INSERT 時に id に値を指定した場合は、正しく動作します。

kawatest=# INSERT INTO src VALUES ( 100, 'WORLD' );
kawatest=# SELECT * FROM src;
 id  |  val
-----+-------
   1 | HELLO
 100 | WORLD
kawatest=# SELECT * FROM dst;
 id  |  val
-----+-------
   2 | HELLO
 100 | WORLD    ← ちゃんと id=100 だった
kawatest=# SELECT currval('src_id_seq');
 currval
---------
       2      ← カウントアップしていない(当たり前か)

serial 型を利用せずに、予めシリアル値を取得しておいて、
上記のように INSERT 時に明示的に値を指定すれば良いのかもしれませんが、
ON INSERT のルールとシーケンスは、併用できないのでしょうか?

http://archives.postgresql.org/pgsql-bugs/2002-11/msg00104.php
のスレッドを見ると、トリガを使うべし、とも読めるのですが、
ルールで対応することはできるのでしょうか?

<ドキュメント>
http://postgresql.jp/document/current/html/rules-update.html

※ルールシステムの動作内容を、正しく理解できていない気がしますが・・・。

-- 
川崎 有亮 Kawasaki Yusuke
http://www.kawa.net/



pgsql-jp メーリングリストの案内