Re: Current transaction is aborted, commands ignored until end of transaction block

From: Leif Biberg Kristensen <leif(at)solumslekt(dot)org>
To: pgsql-sql(at)postgresql(dot)org
Subject: Re: Current transaction is aborted, commands ignored until end of transaction block
Date: 2011-12-30 11:25:08
Message-ID: 201112301225.08946.leif@solumslekt.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-sql

Fredag 30. desember 2011 05.25.22 skrev Jan Bakuwel :
> Of course I can start testing existing values in the database before
> accepting them in the user interface but that's putting the horse behind
> the cart. I much rather use the constraints at the database level to
> tell me a particular update can't be done and do that without loosing
> everything else I happened to have done in that transaction until that
> point.

Here's an example from a plpgsql function I wrote, where a possible violation
of unique constraint on (parent_id, source_text) is checked within the
transaction:

SELECT source_id FROM sources WHERE parent_id = par_id AND source_text = txt
INTO x;
IF NOT FOUND THEN
INSERT INTO sources (parent_id, source_text, sort_order, source_date,
part_type)
VALUES (par_id, txt, srt, true_date_extract(txt), pt) RETURNING
source_id INTO src_id;
ELSE
RAISE NOTICE 'Source % has the same parent id and text as you tried to
enter.', x;
RETURN -x; -- abort the transaction and return the offended source id as a
negative number.
END IF;

I don't know if it's considered good form to issue a RETURN in the middle of a
function on an error condition, but the main point is that you can take an
alternate action when the violation is about to happen. Before I introduced
this test, the PHP interface just barfed all over the place with "transaction
aborted" messages.

Here's another test from the same function, where the alternate action is
basically a no-op:

-- don't violate unique constraint on (source_fk, event_fk) in the
event_citations table.
-- if this source-event association already exists, it's rather pointless to
repeat it.
PERFORM * FROM event_citations WHERE event_fk = event AND source_fk = src_id;
IF NOT FOUND THEN
INSERT INTO event_citations (event_fk, source_fk) VALUES (event,
src_id);
ELSE
RAISE NOTICE 'citation exists';
END IF;

regards, Leif

In response to

Browse pgsql-sql by date

  From Date Subject
Next Message John Fabiani 2011-12-30 14:26:19 avoid the creating the type for setof
Previous Message Thomas Kellerer 2011-12-30 11:18:09 Re: Current transaction is aborted, commands ignored until end of transaction block