BUG #3929: RULE causes unintended update of SEQUENCE - Mailing list pgsql-bugs

From Arjan Tuinhout
Subject BUG #3929: RULE causes unintended update of SEQUENCE
Date
Msg-id 200802051037.m15AbVVZ032313@wwwmaster.postgresql.org
Whole thread Raw
Responses Re: BUG #3929: RULE causes unintended update of SEQUENCE  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-bugs
The following bug has been logged online:

Bug reference:      3929
Logged by:          Arjan Tuinhout
Email address:      at@tuko.nl
PostgreSQL version: 8.1
Operating system:   Kubuntu 6.06 Dapper
Description:        RULE causes unintended update of SEQUENCE
Details:

-- The SQL code explains the problem:
-- I have 2 tables one storing basic data about documents 'doc' and one
storing the revisions 'rev'
-- I add one RULE to make sure that the latest available revision identifier
is available in the 'doc' table
-- The rev_id is generated by a SEQUENCE
-- However the intended code does not work: appearantly the SEQUENCE is
update by calling the RULE; proofed by the workaround.

-- Please help. Thanx. Arjan.


CREATE SEQUENCE id;

CREATE TABLE doc (doc_id INT4 DEFAULT nextval('id') PRIMARY KEY, name TEXT,
curr_rev_id INT4);

CREATE TABLE rev (doc_id INT4 REFERENCES doc, rev_id INT4 DEFAULT
nextval('id') PRIMARY KEY, revision TEXT);

CREATE RULE upd_doc AS ON INSERT TO rev DO ALSO UPDATE doc SET curr_rev_id =
NEW.rev_id WHERE doc_id = NEW.doc_id;

INSERT INTO doc VALUES(1, 'Book on PostgreSQL', NULL);
INSERT INTO rev (doc_id, revision) VALUES (1, 'Revision 1');
INSERT INTO rev (doc_id, revision) VALUES (1, 'Revision 2');

-- The next select statement should yield the current doc version, but
returns nothing...
SELECT * FROM doc NATURAL JOIN rev WHERE curr_rev_id = rev_id;

-- From the next select statement indicates the problem: the RULE does
increment the SEQUENCE id!!!
SELECT * FROM doc NATURAL JOIN rev;

-- A work around, proofing the problem lies in the RULE statement, could
be:
CREATE OR REPLACE RULE upd_doc AS ON INSERT TO rev DO ALSO UPDATE doc SET
curr_rev_id = currval('id')WHERE doc_id = NEW.doc_id;
-- This works but is dangerous... because you need to rely on using the
sequence to create unique identifiers for revisions...)

pgsql-bugs by date:

Previous
From: "Bart Heupers"
Date:
Subject: BUG #3928: INFORMATION_SCHEMA does not give results if a user is allowed only access via ROLE
Next
From: "Markus Eisenmann"
Date:
Subject: BUG #3930: initdb failed - "postgres" not found