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

Commit220e6bf

Browse files
committed
Fix plperl to do recursion safely, and fix a problem with array results.
Add suitable regression tests. Andrew Dunstan
1 parenta1a64bb commit220e6bf

File tree

3 files changed

+128
-19
lines changed

3 files changed

+128
-19
lines changed

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,56 @@ SELECT * from perl_spi_func();
367367
2
368368
(2 rows)
369369

370+
---
371+
--- Test recursion via SPI
372+
---
373+
CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
374+
AS $$
375+
376+
my $i = shift;
377+
foreach my $x (1..$i)
378+
{
379+
return_next "hello $x";
380+
}
381+
if ($i > 2)
382+
{
383+
my $z = $i-1;
384+
my $cursor = spi_query("select * from recurse($z)");
385+
while (defined(my $row = spi_fetchrow($cursor)))
386+
{
387+
return_next "recurse $i: $row->{recurse}";
388+
}
389+
}
390+
return undef;
391+
392+
$$;
393+
SELECT * FROM recurse(2);
394+
recurse
395+
---------
396+
hello 1
397+
hello 2
398+
(2 rows)
399+
400+
SELECT * FROM recurse(3);
401+
recurse
402+
--------------------
403+
hello 1
404+
hello 2
405+
hello 3
406+
recurse 3: hello 1
407+
recurse 3: hello 2
408+
(5 rows)
409+
410+
---
411+
--- Test arrary return
412+
---
413+
CREATE OR REPLACE FUNCTION array_of_text() RETURNS TEXT[][]
414+
LANGUAGE plperl as $$
415+
return [['a"b','c,d'],['e\\f','g']];
416+
$$;
417+
SELECT array_of_text();
418+
array_of_text
419+
-----------------------------
420+
{{"a\"b","c,d"},{"e\\f",g}}
421+
(1 row)
422+

‎src/pl/plperl/plperl.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* ENHANCEMENTS, OR MODIFICATIONS.
3434
*
3535
* IDENTIFICATION
36-
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.84 2005/07/1016:13:13 momjian Exp $
36+
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.85 2005/07/12 01:16:21 tgl Exp $
3737
*
3838
**********************************************************************/
3939

@@ -90,9 +90,6 @@ typedef struct plperl_proc_desc
9090
FmgrInfoarg_out_func[FUNC_MAX_ARGS];
9191
boolarg_is_rowtype[FUNC_MAX_ARGS];
9292
SV*reference;
93-
FunctionCallInfocaller_info;
94-
Tuplestorestate*tuple_store;
95-
TupleDesctuple_desc;
9693
}plperl_proc_desc;
9794

9895

@@ -106,8 +103,11 @@ static HV *plperl_proc_hash = NULL;
106103

107104
staticboolplperl_use_strict= false;
108105

109-
/*this is saved and restored by plperl_call_handler */
106+
/*these are saved and restored by plperl_call_handler */
110107
staticplperl_proc_desc*plperl_current_prodesc=NULL;
108+
staticFunctionCallInfoplperl_current_caller_info;
109+
staticTuplestorestate*plperl_current_tuple_store;
110+
staticTupleDescplperl_current_tuple_desc;
111111

112112
/**********************************************************************
113113
* Forward declarations
@@ -577,10 +577,16 @@ plperl_call_handler(PG_FUNCTION_ARGS)
577577
{
578578
Datumretval;
579579
plperl_proc_desc*save_prodesc;
580+
FunctionCallInfosave_caller_info;
581+
Tuplestorestate*save_tuple_store;
582+
TupleDescsave_tuple_desc;
580583

581584
plperl_init_all();
582585

583586
save_prodesc=plperl_current_prodesc;
587+
save_caller_info=plperl_current_caller_info;
588+
save_tuple_store=plperl_current_tuple_store;
589+
save_tuple_desc=plperl_current_tuple_desc;
584590

585591
PG_TRY();
586592
{
@@ -592,11 +598,17 @@ plperl_call_handler(PG_FUNCTION_ARGS)
592598
PG_CATCH();
593599
{
594600
plperl_current_prodesc=save_prodesc;
601+
plperl_current_caller_info=save_caller_info;
602+
plperl_current_tuple_store=save_tuple_store;
603+
plperl_current_tuple_desc=save_tuple_desc;
595604
PG_RE_THROW();
596605
}
597606
PG_END_TRY();
598607

599608
plperl_current_prodesc=save_prodesc;
609+
plperl_current_caller_info=save_caller_info;
610+
plperl_current_tuple_store=save_tuple_store;
611+
plperl_current_tuple_desc=save_tuple_desc;
600612

601613
returnretval;
602614
}
@@ -897,16 +909,17 @@ plperl_func_handler(PG_FUNCTION_ARGS)
897909
SV*perlret;
898910
Datumretval;
899911
ReturnSetInfo*rsi;
912+
SV*array_ret=NULL;
900913

901914
if (SPI_connect()!=SPI_OK_CONNECT)
902915
elog(ERROR,"could not connect to SPI manager");
903916

904917
prodesc=compile_plperl_function(fcinfo->flinfo->fn_oid, false);
905918

906919
plperl_current_prodesc=prodesc;
907-
prodesc->caller_info=fcinfo;
908-
prodesc->tuple_store=0;
909-
prodesc->tuple_desc=0;
920+
plperl_current_caller_info=fcinfo;
921+
plperl_current_tuple_store=0;
922+
plperl_current_tuple_desc=0;
910923

911924
perlret=plperl_call_perl_func(prodesc,fcinfo);
912925

@@ -958,10 +971,10 @@ plperl_func_handler(PG_FUNCTION_ARGS)
958971
}
959972

960973
rsi->returnMode=SFRM_Materialize;
961-
if (prodesc->tuple_store)
974+
if (plperl_current_tuple_store)
962975
{
963-
rsi->setResult=prodesc->tuple_store;
964-
rsi->setDesc=prodesc->tuple_desc;
976+
rsi->setResult=plperl_current_tuple_store;
977+
rsi->setDesc=plperl_current_tuple_desc;
965978
}
966979
retval= (Datum)0;
967980
}
@@ -1006,7 +1019,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
10061019
{
10071020
/* Return a perl string converted to a Datum */
10081021
char*val;
1009-
SV*array_ret;
10101022

10111023

10121024
if (prodesc->fn_retisarray&&SvTYPE(SvRV(perlret))==SVt_PVAV)
@@ -1024,7 +1036,9 @@ plperl_func_handler(PG_FUNCTION_ARGS)
10241036
Int32GetDatum(-1));
10251037
}
10261038

1027-
SvREFCNT_dec(perlret);
1039+
if (array_ret==NULL)
1040+
SvREFCNT_dec(perlret);
1041+
10281042
returnretval;
10291043
}
10301044

@@ -1526,7 +1540,7 @@ void
15261540
plperl_return_next(SV*sv)
15271541
{
15281542
plperl_proc_desc*prodesc=plperl_current_prodesc;
1529-
FunctionCallInfofcinfo=prodesc->caller_info;
1543+
FunctionCallInfofcinfo=plperl_current_caller_info;
15301544
ReturnSetInfo*rsi= (ReturnSetInfo*)fcinfo->resultinfo;
15311545
MemoryContextcxt;
15321546
HeapTupletuple;
@@ -1553,8 +1567,9 @@ plperl_return_next(SV *sv)
15531567

15541568
cxt=MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
15551569

1556-
if (!prodesc->tuple_store)
1557-
prodesc->tuple_store=tuplestore_begin_heap(true, false,work_mem);
1570+
if (!plperl_current_tuple_store)
1571+
plperl_current_tuple_store=
1572+
tuplestore_begin_heap(true, false,work_mem);
15581573

15591574
if (prodesc->fn_retistuple)
15601575
{
@@ -1590,10 +1605,10 @@ plperl_return_next(SV *sv)
15901605
tuple=heap_form_tuple(tupdesc,&ret,&isNull);
15911606
}
15921607

1593-
if (!prodesc->tuple_desc)
1594-
prodesc->tuple_desc=tupdesc;
1608+
if (!plperl_current_tuple_desc)
1609+
plperl_current_tuple_desc=tupdesc;
15951610

1596-
tuplestore_puttuple(prodesc->tuple_store,tuple);
1611+
tuplestore_puttuple(plperl_current_tuple_store,tuple);
15971612
heap_freetuple(tuple);
15981613
MemoryContextSwitchTo(cxt);
15991614
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,44 @@ while (defined ($y = spi_fetchrow($x))) {
260260
return;
261261
$$ LANGUAGE plperl;
262262
SELECT*from perl_spi_func();
263+
264+
265+
---
266+
--- Test recursion via SPI
267+
---
268+
269+
270+
CREATE OR REPLACEFUNCTIONrecurse(iint) RETURNS SETOFTEXT LANGUAGE plperl
271+
AS $$
272+
273+
my $i= shift;
274+
foreach my $x (1..$i)
275+
{
276+
return_next"hello $x";
277+
}
278+
if ($i>2)
279+
{
280+
my $z= $i-1;
281+
my $cursor= spi_query("select * from recurse($z)");
282+
while (defined(my $row= spi_fetchrow($cursor)))
283+
{
284+
return_next"recurse $i: $row->{recurse}";
285+
}
286+
}
287+
return undef;
288+
289+
$$;
290+
291+
SELECT*FROM recurse(2);
292+
SELECT*FROM recurse(3);
293+
294+
295+
---
296+
--- Test arrary return
297+
---
298+
CREATE OR REPLACEFUNCTIONarray_of_text() RETURNSTEXT[][]
299+
LANGUAGE plperlas $$
300+
return [['a"b','c,d'],['e\\f','g']];
301+
$$;
302+
303+
SELECT array_of_text();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp