Re: Trigger function not executing - Mailing list pgsql-bugs

From Donald Fraser
Subject Re: Trigger function not executing
Date
Msg-id 004401c2d0e8$d6adce20$1664a8c0@DEMOLITION
Whole thread Raw
In response to Trigger function not executing  ("Donald Fraser" <demolish@cwgsy.net>)
Responses Re: Trigger function not executing  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-bugs
----- Original Message -----=20
  From: Donald Fraser=20
  To: pgsql-bugs@postgresql.org=20
  Sent: Thursday, February 06, 2003 11:27 AM
  Subject: [BUGS] Trigger function not executing



  OS: Redhat, kernel 2.4
  PostgreSQL 7.3.1 on i686-pc-linux-gnu, compiled by GCC 2.96

  I have a table that has two triggers functions applied to it
  1) CREATE TRIGGER trig_delete_user BEFORE DELETE ON tbl_user FOR EACH ROW=
 EXECUTE PROCEDURE delete_user();
  2) CREATE TRIGGER trig_insert_sys_user AFTER INSERT OR DELETE OR UPDATE O=
N tbl_user FOR EACH ROW EXECUTE PROCEDURE insert_sys_user();

  The BEFORE trigger function basically does nothing to modify the tuple in=
 any way. It does run a SELECT on the same table to do some routine checks =
and before it can exit the function it sets a global flag to tell the AFTER=
 trigger function what to do.

  The AFTER trigger function resets the flag set by the BEFORE function and=
 then performs some administration commands for users . In this instance it=
 issues a "DROP USER" command.

  I've included the above summary as an insight to where the problem may be.

  Here is the problem:
  If I run SQL such as DELETE FROM tbl_user WHERE id =3D '2'; then I don't =
get any problems.
  If I run SQL such as DELETE FROM tbl_user WHERE id > '40'; and there is o=
nly one record that meets the condition (id > '40') then I don't get any pr=
oblems.
  If I run SQL such as DELETE FROM tbl_user WHERE id > '20'; and there is m=
ore than one record that meets the condition (id > '20') then I get the fol=
lowing problem. The BEFORE trigger function is only being called on the fir=
st record that is being deleted yet the AFTER function is being called on a=
ll of the records - well in this case it only gets to the second record and=
 fails because the flag has not been set by the BEFORE function. Just to re=
-iterate - the BFORE function is very simple - it cannot exit the function =
without setting the flag I have mentioned.

  Have I misunderstood trigger functions or is this a legitimate bug?

  Regards
  Donald Fraser

  ----- Original Message -----=20
  From: "Tom Lane" <tgl@sss.pgh.pa.us>
  To: "Donald Fraser" <demolish@cwgsy.net>
  Cc: <pgsql-bugs@postgresql.org>
  Sent: Thursday, February 06, 2003 2:42 PM
  Subject: Re: [BUGS] Trigger function not executing=20


  > "Donald Fraser" <demolish@cwgsy.net> writes:
  > > If I run SQL such as DELETE FROM tbl_user WHERE id > '20'; and there =
is mor=3D
  > > e than one record that meets the condition (id > '20') then I get the=
 follo=3D
  > > wing problem. The BEFORE trigger function is only being called on the=
 first=3D
  > >  record that is being deleted=20
  >=20
  > I don't believe it --- and you haven't provided any evidence to support
  > your claim.  More than likely, this is just an error in your own trigger
  > code; but with no details it's pointless to speculate.
  >=20
  > regards, tom lane
  >=20
Tom I have had another look at this problem and you were correct in that th=
e trigger functions were being called, just not in the order that I had exp=
ected. There were "no bugs" in my code as such, just a total misunderstandi=
ng on how trigger functions are processed in a SQL command that effects mor=
e than one record - hence the reason why I'm writing this email. I don't wa=
nt other people to be caught out with the same problem and it may well be w=
orth putting a note in the documentation under the trigger manager section =
and correcting the example in Chapter 16.4.=20

I made the following assumption (based on the documents): The sequence of e=
vents for trigger functions would be exactly the same regardless of the SQL=
 statement/s to achieve the same result. That is I thought that for example=
: DELETE FROM tbl_user WHERE id =3D '20'; DELETE FROM tbl_user WHERE id =3D=
 '21';  would produce exactly the same sequence of events as DELETE FROM tb=
l_user WHERE (id >=3D '20' AND id <=3D '21'); This is not the case.

The sequence of events for the first set of SQL statements is as follows:
1: Trigger BEFORE EVENT for record with id =3D 20;
2: Trigger AFTER EVENT for record with id =3D 20;
3: Trigger BEFORE EVENT for record with id =3D 21;
4: Trigger AFTER EVENT for record with id =3D 21;

The sequence of events for the second set of SQL statements is as follows:
1: Trigger BEFORE EVENT for record with id =3D 20;
2: Trigger BEFORE EVENT for record with id =3D 21;
3: Trigger AFTER EVENT for record with id =3D 20;
4: Trigger AFTER EVENT for record with id =3D 21;

According to the example in the documentation - 'Chapter 16.4 Examples', th=
e sequence of events for the DELETE is as follows:
vac=3D> DELETE FROM ttest;
INFO:  trigf (fired before): there are 2 tuples in ttest
INFO:  trigf (fired after ): there are 1 tuples in ttest
INFO:  trigf (fired before): there are 1 tuples in ttest
INFO:  trigf (fired after ): there are 0 tuples in ttest

So you can see that the documented sequence of events is not the same as wh=
at actually happens.
To prove this I created and ran the example from the documentation (cut and=
 paste exactly from the documentation).
Here is the output that I got:

CISX=3D# INSERT INTO ttest VALUES('100');
NOTICE: trigf (fired before): there are 0 tuples in ttest
NOTICE: trigf (fired after ): there are 1 tuples in ttest
INSERT 17497 1
CISX=3D# INSERT INTO ttest VALUES('101');
NOTICE: trigf (fired before): there are 1 tuples in ttest
NOTICE: trigf (fired after ): there are 2 tuples in ttest
INSERT 17498 1
CISX=3D# INSERT INTO ttest VALUES('102');
NOTICE: trigf (fired before): there are 2 tuples in ttest
NOTICE: trigf (fired after ): there are 3 tuples in ttest
INSERT 17499 1
CISX=3D# INSERT INTO ttest VALUES('122');
NOTICE: trigf (fired before): there are 3 tuples in ttest
NOTICE: trigf (fired after ): there are 4 tuples in ttest
INSERT 17500 1
CISX=3D# DELETE FROM ttest WHERE x >=3D '100';
NOTICE: trigf (fired before): there are 4 tuples in ttest
NOTICE: trigf (fired before): there are 3 tuples in ttest
NOTICE: trigf (fired before): there are 2 tuples in ttest
NOTICE: trigf (fired before): there are 1 tuples in ttest
NOTICE: trigf (fired after ): there are 0 tuples in ttest
NOTICE: trigf (fired after ): there are 0 tuples in ttest
NOTICE: trigf (fired after ): there are 0 tuples in ttest
NOTICE: trigf (fired after ): there are 0 tuples in ttest
DELETE 4

As you can see the actual sequence of events differs to what is documented =
and what I had logically expected - hence why I was questioning whether the=
re was a bug with triggers, albeit that I was pointing the finger at the wr=
ong thing. Next time I want be so keen to come forward with a bug without i=
nvestigating it further - sorry for that.

Regards
Donald Fraser.

pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: Bug #894: different result with the same parameterlist in function call
Next
From: Tom Lane
Date:
Subject: Re: Trigger function not executing