pg.ddx.io  pgsql-sql@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Ken Winter <ken@sunward.org>
To: 'PostgreSQL pg-sql list' <pgsql-sql@postgresql.org>
Subject: Rule causes baffling error
Date: Fri, 16 Dec 2005 16:07:19 -0500
Message-ID: <003801c60284$b404a620$6603a8c0@kenxp> (raw)

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 not null 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 AS
	ON UPDATE TO my_data_now
	DO INSTEAD
		(
		/* Update current record, and make it effective 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 expire it 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





view thread (7+ messages)  latest in thread

Message-ID: <003801c60284$b404a620$6603a8c0@kenxp>
Permalink:  ../003801c60284$b404a620$6603a8c0@kenxp/
Also on:    postgresql.org/message-id/003801c60284$b404a620$6603a8c0@kenxp

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-sql@postgresql.org
  Cc: ken@sunward.org
  Subject: Re: Rule causes baffling error
  In-Reply-To: <003801c60284$b404a620$6603a8c0@kenxp>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox