Rule causes baffling error - Mailing list pgsql-sql

From Ken Winter
Subject Rule causes baffling error
Date
Msg-id 003801c60284$b404a620$6603a8c0@kenxp
Whole thread Raw
Responses Re: Rule causes baffling error  (Richard Huxton <dev@archonet.com>)
List pgsql-sql
I'm trying to figure out why a rule gives me a uniqueness violation when I
try to do an update.

I have a table, "my_data", defined as:

create table my_data (id INT8 not null default nextval('person_seq'),effective_date_and_time TIMESTAMP WITH TIME ZONE
notnull default
 
CURRENT_TIMESTAMP,expiration_date_and_time TIMESTAMP WITH TIME ZONE null default
'infinity',user_name VARCHAR(255)null,constraint PK_MY_DATA primary key
(effective_date_and_time, id)
);

I have a view, my_data_now, defined as:

SELECT my_data.id, my_data.user_name, my_data.effective_date_and_time,     my_data.expiration_date_and_time
FROM     my_data
WHERE my_data.effective_date_and_time <= 'now'::text::timestamp(6)
with time zone AND     my_data.expiration_date_and_time >=
'now'::text::timestamp(6) with time zone;

And I have this rule (among others):

CREATE OR REPLACE RULE upd_my_data_now ASON UPDATE TO my_data_nowDO INSTEAD    (    /* Update current record, and make
iteffective now. */    UPDATE my_data        SET id = NEW.id,             user_name = NEW.user_name,
effective_date_and_time=
 
('now'::text)::timestamp(6) with time zone        WHERE effective_date_and_time =
OLD.effective_date_and_time             AND id = OLD.id;    /* Insert a record containing the old values,     and
expireit as of now. */    INSERT INTO my_data (        effective_date_and_time,        expiration_date_and_time,
  id,         user_name)         VALUES (              OLD.effective_date_and_time,
('now'::text)::timestamp(6)with time zone,            OLD.id,             OLD.user_name)    ); 
 

This rule is supposed to (1) cause an update directed to the view
"my_data_now" to be made to the underlying table "my_data", (2) reset the
"effective_date_and_time" of that row to 'now', (3) insert a record
containing the old values into "my_data", and (4) expire that "old" record
by setting its "expiration_date_and_time" to 'now'.

But when I try to do an update against the view "my_data_now" with a query
such as:
    update my_data_now set user_name = 'Suzy' where id = 1;

I get:
ERROR:  duplicate key violates unique constraint "pk_my_data"

Presumably this happens when the rule tries to insert the new row. The new
row does indeed contain the "old" id and effective_date_and_time.  However,
the rule is structured so that the current row's "effective_date_and_time"
gets updated to 'now' *before* the new row is inserted, making its value
different from the old "effective_date_and_time".  So the uniqueness
conflict shouldn't occur.

I figure either there's some bug in my code that I can't see, or else the
PostgreSQL rule processor works in some way that I don't understand.  

In either case, help!

~ TIA
~ Ken




pgsql-sql by date:

Previous
From: Alvaro Herrera
Date:
Subject: Re: Need SQL Help Finding Current Status of members
Next
From: Alexandre Gonçalves Jacarandá
Date:
Subject: Re: Help on function creating