Thread: BUG #3587: EXECUTE and trigger problem

BUG #3587: EXECUTE and trigger problem

From
"cyrus"
Date:
The following bug has been logged online:

Bug reference:      3587
Logged by:          cyrus
Email address:      cdowney@pryermachine.com
PostgreSQL version: 8.1.9
Operating system:   i686-redhat-linux-gnu
Description:        EXECUTE and trigger problem
Details:

I am having problems using the Old record as part of the dynamic command
passed to the Execute statement in a trigger.

The error recived was:
ERROR:  OLD used in query that is not in a rule
CONTEXT:  SQL statement "INSERT INTO public.test_hist  SELECT  OLD.* from
OLD;"
PL/pgSQL function "hist_insert_tr" line 8 at execute statement

Below is the DDL I used to replicate the problem.

create table public.test(itest integer);
create table public.test_hist(      itest integer,
                             "dmodified" TIMESTAMP WITHOUT TIME ZONE DEFAULT
now() NOT NULL
                             );


CREATE OR REPLACE FUNCTION public.hist_insert_tr () RETURNS trigger AS
$body$
declare
       lcDynamicSQL varchar := '';
BEGIN
       --does not work
       --lcDynamicSQL := 'INSERT INTO public.' || TG_ARGV[0] || '_hist
SELECT  OLD.*;';
       --does not work
       lcDynamicSQL := 'INSERT INTO public.' || TG_ARGV[0] || '_hist  SELECT
 OLD.* from OLD;';
       EXECUTE lcDynamicSQL;
       RETURN NULL;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;


CREATE TRIGGER test_after_tr AFTER UPDATE
ON public.test FOR EACH ROW
EXECUTE PROCEDURE public.hist_insert_tr(test);



insert into test (itest) VALUES(1);
update test set itest = 2;



drop table public.test cascade;
drop table public.test_hist;
DROP FUNCTION public.hist_insert_tr();

Re: BUG #3587: EXECUTE and trigger problem

From
Alvaro Herrera
Date:
cyrus wrote:

> I am having problems using the Old record as part of the dynamic command
> passed to the Execute statement in a trigger.

This is not a bug (please don't use the bug report form for support
requests).

Anyway, you may want to check the "tablelog" project in
http://pgfoundry.org/ for code that works for this purpose (or something
similar anyway).


--
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.

Re: BUG #3587: EXECUTE and trigger problem [VASCL:A163D284A86]

From
Cyrus Downey
Date:
Alvaro Herrera wrote:

  cyrus wrote:



    I am having problems using the Old record as part of the dynamic command
passed to the Execute statement in a trigger.



This is not a bug (please don't use the bug report form for support
requests).

Anyway, you may want to check the "tablelog" project in
http://pgfoundry.org/ for code that works for this purpose (or something
similar anyway).




This was not a support request.  I have already solved the problem, but
it much more code than my original method (which does not work). 
According to the documentation I should be able to use the OLD record
in the dynamic command passed to the Execute statement.  

I have attacked my DDL for you to review.

The error received was:
ERROR:  OLD used in query that is not in a rule
CONTEXT:  SQL statement "INSERT INTO public.test_hist  SELECT  OLD.* from
OLD;"
PL/pgSQL function "hist_insert_tr" line 8 at execute statement

Below is the DDL I used to replicate the problem.

create table public.test(itest integer);
create table public.test_hist(      itest integer,
                             "dmodified" TIMESTAMP WITHOUT TIME ZONE DEFAULT
now() NOT NULL
                             );


CREATE OR REPLACE FUNCTION public.hist_insert_tr () RETURNS trigger AS
$body$
declare
       lcDynamicSQL varchar := '';
BEGIN
       --does not work
       --lcDynamicSQL := 'INSERT INTO public.' || TG_ARGV[0] || '_hist
SELECT  OLD.*;';
       --does not work
       lcDynamicSQL := 'INSERT INTO public.' || TG_ARGV[0] || '_hist  SELECT
 OLD.* from OLD;';
       EXECUTE lcDynamicSQL;
       RETURN NULL;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;


CREATE TRIGGER test_after_tr AFTER UPDATE
ON public.test FOR EACH ROW
EXECUTE PROCEDURE public.hist_insert_tr(test);



insert into test (itest) VALUES(1);
update test set itest = 2;



drop table public.test cascade;
drop table public.test_hist;
DROP FUNCTION public.hist_insert_tr();

Bug reference:      3587
Logged by:          cyrus
Email address:      <a class="moz-txt-link-abbreviated"
 href="mailto:cdowney@pryermachine.com">cdowney@pryermachine.com
PostgreSQL version: 8.1.9
Operating system:   i686-redhat-linux-gnu
Description:        EXECUTE and trigger problem

Re: BUG #3587: EXECUTE and trigger problem [VASCL:A163D284A86]

From
Tom Lane
Date:
Cyrus Downey <cdowney@pryermachine.com> writes:
> According to the documentation I should be able to use the OLD record
> in the dynamic command passed to the Execute statement.

The documentation promises no such thing.

            regards, tom lane

Re: BUG #3587: EXECUTE and trigger problem [VASCL:A1226546842]

From
Cyrus Downey
Date:
but the documentation does not say I shouldn't be able to do it. 
Additionally, an alternate method (which was not included) using
temporary tables works fine.  It fails when switching to the old record.

thanks
cyrus

Tom Lane wrote:

  Cyrus Downey <cdowney@pryermachine.com> writes:


    According to the documentation I should be able to use the OLD record
in the dynamic command passed to the Execute statement.



The documentation promises no such thing.

            regards, tom lane