Search Postgresql Archives

Re: a row not deletes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 2014-04-27 10:23:18 +0200, Rafał Pietrak wrote:
> I've just experienced an unexpected (for me) "loss" of DELETE. Is this a
> feature or a bug (postgres v.s. SQL)?
> 
> -------------------- test case -------------------------
> test=# CREATE  TABLE test (a int, b text);
> test=# INSERT  INTO  test (a,b) values (1,'asd');
> test=# INSERT  INTO  test (a,b) values (2,'dfg');
> test=# INSERT  INTO  test (a,b) values (3,'ghj');
> test=# CREATE or replace FUNCTION test_del () returns trigger language
> plpgsql as $$ begin  update test t set b = 'will delete this' where
> t.a=old.a; return old; end; $$;
> test=# CREATE  TRIGGER  test_trig BEFORE DELETE ON test for each row execute
> procedure test_del();
> 
> test=# DELETE FROM  test where a=2;
> DELETE 0
> test=# SELECT * from test;
>  a  |  b
> ----+-----
>   1 | asd
>   3 | ghj
>   2 | will delete this
> (3 rows)
> --------------------------------------------------------
> 
> e.g.: an indicated row is not deleted, despite the fact, that the selector
> wasn't changed by the intermediate UPDATE.  I understand, that the bucket
> was changed by the update, but should that matter?

I guess you're using 9.2 or older? You are not allowed to update the
deleted row in a BEFORE trigger. The source has this comment about it
(in 9.3 onwards):

/*
 * The target tuple was already updated or deleted by the
 * current command, or by a later command in the current
 * transaction.  The former case is possible in a join DELETE
 * where multiple tuples join to the same target tuple. This
 * is somewhat questionable, but Postgres has always allowed
 * it: we just ignore additional deletion attempts.
 *
 * The latter case arises if the tuple is modified by a
 * command in a BEFORE trigger, or perhaps by a command in a
 * volatile function used in the query.  In such situations we
 * should not ignore the deletion, but it is equally unsafe to
 * proceed.  We don't want to discard the original DELETE
 * while keeping the triggered actions based on its deletion;
 * and it would be no better to allow the original DELETE
 * while discarding updates that it triggered.  The row update
 * carries some information that might be important according
 * to business rules; so throwing an error is the only safe
 * course.
 *
 * If a trigger actually intends this type of interaction, it
 * can re-execute the DELETE and then return NULL to cancel
 * the outer delete.
 */
if (hufd.cmax != estate->es_output_cid)
        ereport(ERROR,
                        (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
                         errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
                         errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));



Greetings,

Andres Freund

-- 
 Andres Freund	                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux