Thread: double insert on inherited table with where constraint based on sequence

double insert on inherited table with where constraint based on sequence

From
"Andrew Hammond"
Date:
Perhaps I'm missing something here, but it looks like I'm getting an
insert into both the parent and child tables when my RULE's where
clause is based on a DEFAULT generated from a sequence. It looks like
nextval on the sequence is called 3 times for every insert.

I don't know if this is properly a bug or just un-expected behaviour.
It seems very counter-intuitive since the rule says DO INSTEAD so ISTM
that either one or the other insert should happen.

ahammond=# \d t2
                         Table "public.t2"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('t2_id_seq'::regclass)
 name   | text    | not null
Indexes:
    "t2_pkey" PRIMARY KEY, btree (id)
    "t2_name_key" UNIQUE, btree (name)
    "t2_test" btree ((name::integer)) WHERE is_number(name)
Rules:
    t2_part AS
    ON INSERT TO t2
   WHERE new.id > 10 DO INSTEAD  INSERT INTO t2_child (id, name)
  VALUES (new.id, new.name)

ahammond=# SELECT * FROM t2;
 id | name
----+-------
  1 | one
  2 | two
  3 | three
  4 | 4
  5 | 5
(5 rows)

ahammond=# CREATE TABLE t2_child (CHECK (id > 10)) INHERITS (t2);
CREATE TABLE

ahammond=# CREATE RULE t2_part AS ON INSERT TO t2 WHERE id > 10 DO
INSTEAD INSERT INTO t2_child VALUES (NEW.id, NEW.name);
CREATE RULE

ahammond=# INSERT INTO t2 (name) VALUES ('six');
INSERT 0 1
ahammond=# INSERT INTO t2 (name) VALUES ('seven');
INSERT 0 1
ahammond=# INSERT INTO t2 (name) VALUES ('eight');
INSERT 0 0
ahammond=# INSERT INTO t2 (name) VALUES ('9');
INSERT 0 0
ahammond=# INSERT INTO t2 (name) VALUES ('ten');
INSERT 0 0
ahammond=# INSERT INTO t2 (name) VALUES ('11');
INSERT 0 0
ahammond=# INSERT INTO t2 (name) VALUES ('12');
INSERT 0 0
ahammond=# SELECT * FROM t2;
 id | name
----+-------
  1 | one
  2 | two
  3 | three
  4 | 4
  5 | 5
  7 | six
 10 | seven
 12 | seven                     ?
 15 | eight
 18 | 9
 21 | ten
 24 | 11
 27 | 12
(13 rows)

ahammond=# SELECT * FROM ONLY t2 ;
 id | name
----+-------
  1 | one
  2 | two
  3 | three
  4 | 4
  5 | 5
  7 | six
 10 | seven
(7 rows)

ahammond=# SELECT * FROM t2_child ;
 id | name
----+-------
 12 | seven
 15 | eight
 18 | 9
 21 | ten
 24 | 11
 27 | 12
(6 rows)

Note that the "seven" entry appears twice.

Drew
"Andrew Hammond" <andrew.george.hammond@gmail.com> writes:
> Rules:
>     t2_part AS
>     ON INSERT TO t2
>    WHERE new.id > 10 DO INSTEAD  INSERT INTO t2_child (id, name)
>   VALUES (new.id, new.name)

"new.id" is replaced by "nextval('t2_id_seq'::regclass)" each time it
appears ... which will be four separate times, viz the two evaluations
of the WHERE clause and the two VALUES clauses.

Basically, volatile functions and rules do not mix.  Consider using
a trigger on t2 instead to redirect the insert somewhere else.

            regards, tom lane