[PL/PGSQL] (Bug/Feature problem) with recursive Trigger

From: "Froggy / Froggy Corp(dot)" <froggy(at)froggycorp(dot)com>
To: pgsql-general(at)postgresql(dot)org
Subject: [PL/PGSQL] (Bug/Feature problem) with recursive Trigger
Date: 2006-05-27 18:27:01
Message-ID: 447899F5.2768822B@froggycorp.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hello,

I got some problem on trigger which call them self for UPDATE
BEFORE/AFTER.

Here is some test :

The UPDATE test function/table :
--------------------------------

------8<------------8<----------------8<----------
CREATE SEQUENCE id_my_table_seq;
CREATE table "my_table" (
"id_my_table" int4 DEFAULT nextval('id_my_table_seq') PRIMARY KEY,
"row0" text,
"row1" text,
"row2" text
);
INSERT INTO my_table (id_my_table, row0, row1, row2) VALUES (10,
'data0', 'data1', 'data2');

CREATE OR REPLACE FUNCTION my_table_before_update() RETURNS trigger AS '
DECLARE
BEGIN

IF OLD.row0 <> NEW.row0 THEN
RAISE NOTICE ''test1 %'', OLD.row0;
RAISE NOTICE ''test2 %'', NEW.row0;
UPDATE my_table SET row1 = \'toto\' WHERE id_my_table =
NEW.id_my_table;
RAISE NOTICE ''test3 %'', OLD.row0;
RAISE NOTICE ''test4 %'', NEW.row0;
UPDATE my_table SET row1 = \'tata\' WHERE id_my_table =
NEW.id_my_table;
RAISE NOTICE ''test5 %'', OLD.row0;
RAISE NOTICE ''test6 %'', NEW.row0;
END IF;

RETURN NEW;
END;
' LANGUAGE plpgsql;
CREATE TRIGGER my_table_before_update BEFORE UPDATE ON my_table FOR EACH
ROW EXECUTE PROCEDURE my_table_before_update();

CREATE OR REPLACE FUNCTION my_table_after_update() RETURNS trigger AS '
DECLARE
BEGIN

RAISE NOTICE ''test7 %'', OLD.row0;
RAISE NOTICE ''test8 %'', NEW.row0;

RETURN NEW;
END;
' LANGUAGE plpgsql;
CREATE TRIGGER my_table_after_update AFTER UPDATE ON my_table FOR EACH
ROW EXECUTE PROCEDURE my_table_after_update();
------8<------------8<----------------8<----------

The test for these trigger :
----------------------------

UPDATE my_table set row0 = 'my_test' WHERE id_my_table = 10;

Result :
--------
On a 7.4.7 :
UPDATE my_table set row0 = 'my_test' WHERE id_my_table = 10;
NOTICE: test1 data0
NOTICE: test2 my_test
NOTICE: test3 data0
NOTICE: test4 my_test
NOTICE: test5 data0
NOTICE: test6 my_test
NOTICE: test7 data0
NOTICE: test8 data0
NOTICE: test7 data0
NOTICE: test8 data0

on a 8.1.4 (without context) :
test=# update my_table set row0 = 'my_test' WHERE id_my_table = 10;
NOTICE: test1 data0
NOTICE: test2 my_test
NOTICE: test7 data0
NOTICE: test8 data0
NOTICE: test3 data0
NOTICE: test4 my_test
NOTICE: test7 data0
NOTICE: test8 data0
NOTICE: test5 data0
NOTICE: test6 my_test

PG7 dont make recursiv, it wait for the end of the trigger BEFORE_UPDATE
to call the new UPDATE stat and forgot the 3rd AFTER_UPDATE. PG8 is
better, it call trigger like real recursiv fonction, but allways dismiss
the 3rd AFTER UPDATE.

Logically, the answer should be :

NOTICE: test1 data0
NOTICE: test2 my_test
NOTICE: test7 data0
NOTICE: test8 data0
NOTICE: test3 data0
NOTICE: test4 my_test
NOTICE: test7 data0
NOTICE: test8 data0
NOTICE: test5 data0
NOTICE: test6 my_test
NOTICE: test7 data0
NOTICE: test8 my_test

At beginning, i made a test to see how pl/pgsql make real recursiv with
an insert function which work :

-----------8<-----------8<-----------8<-----------8<---------------
CREATE SEQUENCE id_test_seq;
CREATE table "test" (
"id_test" int4 DEFAULT nextval(id_test_seq) PRIMARY KEY,
"test" text,
"other_row" text,
);

CREATE OR REPLACE FUNCTION test_insert() RETURNS trigger AS '
DECLARE
categorie_mere RECORD;
categorie_mere_lien RECORD;
RecTmp RECORD;
BEGIN

RAISE NOTICE ''begginning'';

IF NEW.test = ''test'' THEN
INSERT INTO test (test) VALUES (''toto'');
END IF;

RAISE NOTICE ''end'';

RETURN NEW;

END;
' LANGUAGE plpgsql;

CREATE TRIGGER test_insert BEFORE INSERT ON test FOR EACH ROW EXECUTE
PROCEDURE test_insert();

-----------8<-----------8<-----------8<-----------8<---------------

With a :

INSERT INTO test (test) values ('test');

You obtain in each case :

NOTICE: begginning
NOTICE: begginning
NOTICE: end
NOTICE: end

-------------------------------------------------------------

In fact, what i dont understand, its why PG dont forget to make the 2
update inside the main update, but after, forgot to make the last one.

Any idea ?

Regards,

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Eric Montague 2006-05-27 18:29:39 psql: krb5_sendauth: Bad application version was sent (via sendauth) - Windows 2000, MIT Kerberos, PG v 8.1.1
Previous Message Rafal Pietrak 2006-05-27 18:19:48 Re: a row disapearing