Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6b449d9

Browse files
committed
Fix declaration of $_TD in "strict" trigger functions
This was broken in commitef19dc6 bythe Bunce/Hunsaker/Dunstan team, which moved the declaration fromplperl_create_sub to plperl_call_perl_trigger_func. This doesn'tactually work because the validator code would not find the variabledeclared; and even if you manage to get past the validator, it stilldoesn't work because get_sv("_TD", GV_ADD) doesn't have the expectedeffect. The only reason this got beyond testing is that it only failsin strict mode.We need to declare it as a global just like %_SHARED; it is simpler thantrying to actually do what the patch initially intended, and is said tohave 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
1 parentea896da commit6b449d9

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

‎src/pl/plperl/expected/plperl_trigger.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,35 @@ SELECT * FROM trigger_test;
255255
5 | third line(modified by trigger)(modified by trigger) | ("(5)")
256256
(4 rows)
257257

258+
DROP TRIGGER "test_valid_id_trig" ON trigger_test;
259+
CREATE OR REPLACE FUNCTION trigger_recurse() RETURNS trigger AS $$
260+
use strict;
261+
262+
if ($_TD->{new}{i} == 10000)
263+
{
264+
spi_exec_query("insert into trigger_test (i, v) values (20000, 'child');");
265+
266+
if ($_TD->{new}{i} != 10000)
267+
{
268+
die "recursive trigger modified: ". $_TD->{new}{i};
269+
}
270+
}
271+
return;
272+
$$ LANGUAGE plperl;
273+
CREATE TRIGGER "test_trigger_recurse" BEFORE INSERT ON trigger_test
274+
FOR EACH ROW EXECUTE PROCEDURE "trigger_recurse"();
275+
INSERT INTO trigger_test (i, v) values (10000, 'top');
276+
SELECT * FROM trigger_test;
277+
i | v | foo
278+
-------+------------------------------------------------------+---------
279+
1 | first line(modified by trigger) | ("(2)")
280+
2 | second line(modified by trigger) | ("(3)")
281+
4 | immortal | ("(4)")
282+
5 | third line(modified by trigger)(modified by trigger) | ("(5)")
283+
20000 | child |
284+
10000 | top |
285+
(6 rows)
286+
258287
CREATE OR REPLACE FUNCTION immortal() RETURNS trigger AS $$
259288
if ($_TD->{old}{v} eq $_TD->{args}[0])
260289
{

‎src/pl/plperl/plc_perlboot.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# src/pl/plperl/plc_perlboot.pl
22

33
use 5.008001;
4-
use varsqw(%_SHARED);
4+
use varsqw(%_SHARED $_TD);
55

66
PostgreSQL::InServer::Util::bootstrap();
77

‎src/pl/plperl/plperl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,8 +1976,11 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
19761976
ENTER;
19771977
SAVETMPS;
19781978

1979-
TDsv=get_sv("_TD",GV_ADD);
1980-
SAVESPTR(TDsv);/* local $_TD */
1979+
TDsv=get_sv("_TD",0);
1980+
if (!TDsv)
1981+
elog(ERROR,"couldn't fetch $_TD");
1982+
1983+
save_item(TDsv);/* local $_TD */
19811984
sv_setsv(TDsv,td);
19821985

19831986
PUSHMARK(sp);

‎src/pl/plperl/sql/plperl_trigger.sql

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,30 @@ UPDATE trigger_test SET i = 100 where i=1;
122122

123123
SELECT*FROM trigger_test;
124124

125+
DROPTRIGGER"test_valid_id_trig"ON trigger_test;
126+
127+
CREATE OR REPLACEFUNCTIONtrigger_recurse() RETURNS triggerAS $$
128+
use strict;
129+
130+
if ($_TD->{new}{i}==10000)
131+
{
132+
spi_exec_query("insert into trigger_test (i, v) values (20000, 'child');");
133+
134+
if ($_TD->{new}{i}!=10000)
135+
{
136+
die"recursive trigger modified:". $_TD->{new}{i};
137+
}
138+
}
139+
return;
140+
$$ LANGUAGE plperl;
141+
142+
CREATETRIGGER "test_trigger_recurse" BEFORE INSERTON trigger_test
143+
FOR EACH ROW EXECUTE PROCEDURE"trigger_recurse"();
144+
145+
INSERT INTO trigger_test (i, v)values (10000,'top');
146+
147+
SELECT*FROM trigger_test;
148+
125149
CREATE OR REPLACEFUNCTIONimmortal() RETURNS triggerAS $$
126150
if ($_TD->{old}{v} eq $_TD->{args}[0])
127151
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp