7.4 and 7.3.5 showstopper (was: Re: Bug in Rule+Foreing key constrain?)

From: Jan Wieck <JanWieck(at)Yahoo(dot)com>
To: Michele Bendazzoli <mickymouse(at)mickymouse(dot)it>
Cc: pgsql-sql <pgsql-sql(at)postgresql(dot)org>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: 7.4 and 7.3.5 showstopper (was: Re: Bug in Rule+Foreing key constrain?)
Date: 2003-10-30 19:13:01
Message-ID: 3FA162BD.8060409@Yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-sql

Confirmed, that's a bug - pgsql-hackers CC'd and scipt for full
reproduction attached.

This can also be reproduced in 7.4-beta5.

My guess out of the blue would be, that the rewriter expands the insert
into one insert with the where clause, one update with the negated where
clause. Executed in that order, they are both true ... first there is no
such row, the insert happens, second the row exists and is being updated.

IIRC the refint trigger queue run at the end of the whole statement
tries to heap_fetch() the originally inserted tuple, which is invisible
by that time. I seem to remember that the original version did fetch
them with some snapshot override mode to get it anyway and fire the
trigger. That apparently does not happen any more, so now the duty would
be up to the on update refint trigger which ... er ... recently got
fixed not to check non-changed key references any more ... duh.

I will look a bit deeper into it later tonight. I think if we let the on
update refint trigger check the referenced key again if the old tuple
has xmin = current_xid we should be fine.

Thanks for reporting, Michele. In the meantime, you might want to use a
BEFORE INSERT trigger in PL/pgSQL that tries to UPDATE the row and if
GET DIAGNOSTICS tells it it succeeded, returns NULL to suppress the
INSERT. That should work around the bug for the time being.

Jan

Michele Bendazzoli wrote:

> On Thu, 2003-10-30 at 18:29, Jan Wieck wrote:
>
>> Not entirely. On which table(s) are the REFERENCES constraints and are
>> they separate per column constraints or are they multi-column constraints?
>
> here are the constraints of the abilitazione table
>
> ALTER TABLE public.abilitazione
> ADD CONSTRAINT abilitazione_pkey PRIMARY KEY(comuneid, cassonettoid,
> chiaveid);
>
> ALTER TABLE public.abilitazione
> ADD CONSTRAINT abilitazione_cassonettoid_fkey FOREIGN KEY (comuneid,
> cassonettoid) REFERENCES public.cassonetto (comuneid, cassonettoid) ON
> UPDATE RESTRICT ON DELETE RESTRICT;
>
> ALTER TABLE public.abilitazione
> ADD CONSTRAINT abilitazione_chiaveid_fkey FOREIGN KEY (comuneid,
> chiaveid) REFERENCES public.chiave (comuneid, chiaveid) ON UPDATE
> RESTRICT ON DELETE RESTRICT;
>
> here those of cassonetto and chiave:
>
> ALTER TABLE public.cassonetto
> ADD CONSTRAINT cassonetto_pkey PRIMARY KEY(comuneid, cassonettoid);
>
> ALTER TABLE public.chiave
> ADD CONSTRAINT chiave_pkey PRIMARY KEY(comuneid, chiaveid);
>
> I get the SQL from pgAdmin3 (great piece of sofware!;-)
>
>> It's usually best to cut'n'paste the CREATE TABLE or ALTER TABLE
>> statements that are used to create the constraints. That way we know
>> exactly what you're talking about.
>
> Excuse me for the missing SQL, but i had tried to keep the message as
> simple as possible.
>
> The unique difference form when the exception was raised and now (that
> it isn't) is the rule added:
>
> CREATE OR REPLACE RULE abilita_ins_rl AS ON INSERT TO abilitazione
> WHERE (EXISTS (
> SELECT 1 FROM abilitazione
> WHERE (((abilitazione.comuneid = new.comuneid )
> AND (abilitazione.cassonettoid = new.cassonettoid ))
> AND (abilitazione.chiaveid = new.chiaveid ))))ù
> DO INSTEAD UPDATE abilitazione SET abilitata = new.abilitata
> WHERE (((abilitazione.comuneid = new.comuneid )
> AND (abilitazione.cassonettoid = new.cassonettoid ))
> AND (abilitazione.chiaveid = new.chiaveid ));
>
> I hope now is more clear.
>
> The version is that come with debian unstable (7.3.4 if I remember
> correctly)
>
> Thank you for the immediate responses
>
> ciao, Michele

--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#================================================== JanWieck(at)Yahoo(dot)com #

Attachment Content-Type Size
testdb.sh text/plain 1.4 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeroen T. Vermeulen 2003-10-30 19:24:13 PQunescapeBytea code
Previous Message Michele Bendazzoli 2003-10-30 19:01:34 Re: Bug in Rule+Foreing key constrain?

Browse pgsql-sql by date

  From Date Subject
Next Message Tomasz Myrta 2003-10-30 19:14:13 Re: strange postgresql failure
Previous Message Michele Bendazzoli 2003-10-30 19:01:34 Re: Bug in Rule+Foreing key constrain?