Re: Stange "duplicate key value violates unique constraint" after "delete" at ON UPDATE trigger

From: Dmitry Koterov <dmitry(at)koterov(dot)ru>
To: "Julian v(dot) Bock" <bock(at)openit(dot)de>
Cc: Postgres General <pgsql-general(at)postgresql(dot)org>
Subject: Re: Stange "duplicate key value violates unique constraint" after "delete" at ON UPDATE trigger
Date: 2012-04-26 11:39:50
Message-ID: CA+CZih7HYr=f_6XM1wuFJP+taT9AGwBbBY+DouQ33vUVHypJqQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

I'm not sure the cause is that DELETE does not see the row.

Seems the following method solves the problem when 2 same-time transactions
are active:

CREATE FUNCTION a_tr() RETURNS trigger AS
$body$
DECLARE
tmp INTEGER;
BEGIN
-- Lock until the mathed entry (possibly phantom - i.e. not yet
committed
-- by another transaction) is released.
SELECT i INTO tmp FROM a WHERE i = NEW.i FOR UPDATE;

-- The lock is released here in one of two cases:
-- 1. Matched row was phantom, so tmp IS NULL now.
-- 2. Matched row was real and committed, so tmp holds its ID.
-- So we cannot use ID in tmp - it is not always returned. That's why
we have to
-- duplicate the selection predicate above...
DELETE FROM a WHERE i = NEW.i;

RETURN NEW;
END;
$body$
LANGUAGE 'plpgsql';

But this method still does not work if 3 or more transactions are active
(if I commit first and commit second, the third fails with "duplicate key"
error).

Are there any universal method which could be implemented purely in a
trigger?..

On Fri, Jan 27, 2012 at 3:45 PM, Julian v. Bock <bock(at)openit(dot)de> wrote:

> Hi
>
> >>>>> "DK" == Dmitry Koterov <dmitry(at)koterov(dot)ru> writes:
>
> DK> create table a(i integer);
> DK> CREATE UNIQUE INDEX a_idx ON a USING btree (i);
> DK> CREATE FUNCTION a_tr() RETURNS trigger AS
> DK> $body$
> DK> BEGIN
> DK> DELETE FROM a WHERE i = NEW.i;
> DK> RETURN NEW;
> DK> END;
> DK> $body$
> DK> LANGUAGE 'plpgsql';
> DK> CREATE TRIGGER a_tr BEFORE INSERT ON a FOR EACH ROW EXECUTE PROCEDURE
> DK> a_tr();
>
> The DELETE doesn't see the row the other transaction inserted and
> doesn't delete anything (and doesn't block). This happens later when the
> row is inserted and the index is updated.
>
> You can try the insert and catch the unique violation in a loop (see
> http://www.postgresql.org/docs/9.1/static/plpgsql-control-structures.html)
> although that won't work with a BEFORE trigger.
>
> Regards,
> Julian
>
> --
> Julian v. Bock Projektleitung Software-Entwicklung
> OpenIT GmbH Tel +49 211 239 577-0
> In der Steele 33a-41 Fax +49 211 239 577-10
> D-40599 Düsseldorf http://www.openit.de
> ________________________________________________________________
> HRB 38815 Amtsgericht Düsseldorf USt-Id DE 812951861
> Geschäftsführer: Oliver Haakert, Maurice Kemmann
>
> --
> Sent via pgsql-general mailing list (pgsql-general(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Dmitry Koterov 2012-04-26 14:29:14 Re: Stange "duplicate key value violates unique constraint" after "delete" at ON UPDATE trigger
Previous Message Pavel Iacovlev 2012-04-26 11:03:15 R-tree parallel index creation