mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Fix declaration of $_TD in "strict" trigger functions
This was broken in commit ef19dc6d39
by
the Bunce/Hunsaker/Dunstan team, which moved the declaration from
plperl_create_sub to plperl_call_perl_trigger_func. This doesn't
actually work because the validator code would not find the variable
declared; and even if you manage to get past the validator, it still
doesn't work because get_sv("_TD", GV_ADD) doesn't have the expected
effect. The only reason this got beyond testing is that it only fails
in strict mode.
We need to declare it as a global just like %_SHARED; it is simpler than
trying to actually do what the patch initially intended, and is said to
have the same performance benefit.
As a more serious issue, fix $_TD not being properly local()ized,
meaning nested trigger functions would clobber $_TD.
Alex Hunsaker, per test report from Greg Mullane
This commit is contained in:
parent
ea896da394
commit
6b449d9051
@ -255,6 +255,35 @@ SELECT * FROM trigger_test;
|
|||||||
5 | third line(modified by trigger)(modified by trigger) | ("(5)")
|
5 | third line(modified by trigger)(modified by trigger) | ("(5)")
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
|
DROP TRIGGER "test_valid_id_trig" ON trigger_test;
|
||||||
|
CREATE OR REPLACE FUNCTION trigger_recurse() RETURNS trigger AS $$
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
if ($_TD->{new}{i} == 10000)
|
||||||
|
{
|
||||||
|
spi_exec_query("insert into trigger_test (i, v) values (20000, 'child');");
|
||||||
|
|
||||||
|
if ($_TD->{new}{i} != 10000)
|
||||||
|
{
|
||||||
|
die "recursive trigger modified: ". $_TD->{new}{i};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
$$ LANGUAGE plperl;
|
||||||
|
CREATE TRIGGER "test_trigger_recurse" BEFORE INSERT ON trigger_test
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE "trigger_recurse"();
|
||||||
|
INSERT INTO trigger_test (i, v) values (10000, 'top');
|
||||||
|
SELECT * FROM trigger_test;
|
||||||
|
i | v | foo
|
||||||
|
-------+------------------------------------------------------+---------
|
||||||
|
1 | first line(modified by trigger) | ("(2)")
|
||||||
|
2 | second line(modified by trigger) | ("(3)")
|
||||||
|
4 | immortal | ("(4)")
|
||||||
|
5 | third line(modified by trigger)(modified by trigger) | ("(5)")
|
||||||
|
20000 | child |
|
||||||
|
10000 | top |
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION immortal() RETURNS trigger AS $$
|
CREATE OR REPLACE FUNCTION immortal() RETURNS trigger AS $$
|
||||||
if ($_TD->{old}{v} eq $_TD->{args}[0])
|
if ($_TD->{old}{v} eq $_TD->{args}[0])
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# src/pl/plperl/plc_perlboot.pl
|
# src/pl/plperl/plc_perlboot.pl
|
||||||
|
|
||||||
use 5.008001;
|
use 5.008001;
|
||||||
use vars qw(%_SHARED);
|
use vars qw(%_SHARED $_TD);
|
||||||
|
|
||||||
PostgreSQL::InServer::Util::bootstrap();
|
PostgreSQL::InServer::Util::bootstrap();
|
||||||
|
|
||||||
|
@ -1976,8 +1976,11 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
|
|||||||
ENTER;
|
ENTER;
|
||||||
SAVETMPS;
|
SAVETMPS;
|
||||||
|
|
||||||
TDsv = get_sv("_TD", GV_ADD);
|
TDsv = get_sv("_TD", 0);
|
||||||
SAVESPTR(TDsv); /* local $_TD */
|
if (!TDsv)
|
||||||
|
elog(ERROR, "couldn't fetch $_TD");
|
||||||
|
|
||||||
|
save_item(TDsv); /* local $_TD */
|
||||||
sv_setsv(TDsv, td);
|
sv_setsv(TDsv, td);
|
||||||
|
|
||||||
PUSHMARK(sp);
|
PUSHMARK(sp);
|
||||||
|
@ -122,6 +122,30 @@ UPDATE trigger_test SET i = 100 where i=1;
|
|||||||
|
|
||||||
SELECT * FROM trigger_test;
|
SELECT * FROM trigger_test;
|
||||||
|
|
||||||
|
DROP TRIGGER "test_valid_id_trig" ON trigger_test;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION trigger_recurse() RETURNS trigger AS $$
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
if ($_TD->{new}{i} == 10000)
|
||||||
|
{
|
||||||
|
spi_exec_query("insert into trigger_test (i, v) values (20000, 'child');");
|
||||||
|
|
||||||
|
if ($_TD->{new}{i} != 10000)
|
||||||
|
{
|
||||||
|
die "recursive trigger modified: ". $_TD->{new}{i};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
$$ LANGUAGE plperl;
|
||||||
|
|
||||||
|
CREATE TRIGGER "test_trigger_recurse" BEFORE INSERT ON trigger_test
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE "trigger_recurse"();
|
||||||
|
|
||||||
|
INSERT INTO trigger_test (i, v) values (10000, 'top');
|
||||||
|
|
||||||
|
SELECT * FROM trigger_test;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION immortal() RETURNS trigger AS $$
|
CREATE OR REPLACE FUNCTION immortal() RETURNS trigger AS $$
|
||||||
if ($_TD->{old}{v} eq $_TD->{args}[0])
|
if ($_TD->{old}{v} eq $_TD->{args}[0])
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user