Обсуждение: BUG #3587: EXECUTE and trigger problem
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();
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.
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
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
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