Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
220e6bfc
Commit
220e6bfc
authored
Jul 12, 2005
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix plperl to do recursion safely, and fix a problem with array results.
Add suitable regression tests. Andrew Dunstan
parent
a1a64bb7
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
128 additions
and
19 deletions
+128
-19
src/pl/plperl/expected/plperl.out
src/pl/plperl/expected/plperl.out
+53
-0
src/pl/plperl/plperl.c
src/pl/plperl/plperl.c
+34
-19
src/pl/plperl/sql/plperl.sql
src/pl/plperl/sql/plperl.sql
+41
-0
No files found.
src/pl/plperl/expected/plperl.out
View file @
220e6bfc
...
...
@@ -367,3 +367,56 @@ SELECT * from perl_spi_func();
2
(2
rows)
---
--- Test recursion via SPI
---
CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
AS $$
my $i = shift;
foreach my $x (1..$i)
{
return_next "hello $x";
}
if ($i > 2)
{
my $z = $i-1;
my $cursor = spi_query("select * from recurse($z)");
while (defined(my $row = spi_fetchrow($cursor)))
{
return_next "recurse $i: $row->{recurse}";
}
}
return undef;
$$;
SELECT * FROM recurse(2);
recurse
---------
hello 1
hello 2
(2
rows)
SELECT * FROM recurse(3);
recurse
--------------------
hello 1
hello 2
hello 3
recurse 3: hello 1
recurse 3: hello 2
(5
rows)
---
--- Test arrary return
---
CREATE OR REPLACE FUNCTION array_of_text() RETURNS TEXT[][]
LANGUAGE plperl as $$
return [['a"b','c,d'],['e\\f','g']];
$$;
SELECT array_of_text();
array_of_text
-----------------------------
{{"a\"b","c,d"},{"e\\f",g}}
(1
row)
src/pl/plperl/plperl.c
View file @
220e6bfc
...
...
@@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.8
4 2005/07/10 16:13:13 momjian
Exp $
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.8
5 2005/07/12 01:16:21 tgl
Exp $
*
**********************************************************************/
...
...
@@ -90,9 +90,6 @@ typedef struct plperl_proc_desc
FmgrInfo
arg_out_func
[
FUNC_MAX_ARGS
];
bool
arg_is_rowtype
[
FUNC_MAX_ARGS
];
SV
*
reference
;
FunctionCallInfo
caller_info
;
Tuplestorestate
*
tuple_store
;
TupleDesc
tuple_desc
;
}
plperl_proc_desc
;
...
...
@@ -106,8 +103,11 @@ static HV *plperl_proc_hash = NULL;
static
bool
plperl_use_strict
=
false
;
/* th
is is
saved and restored by plperl_call_handler */
/* th
ese are
saved and restored by plperl_call_handler */
static
plperl_proc_desc
*
plperl_current_prodesc
=
NULL
;
static
FunctionCallInfo
plperl_current_caller_info
;
static
Tuplestorestate
*
plperl_current_tuple_store
;
static
TupleDesc
plperl_current_tuple_desc
;
/**********************************************************************
* Forward declarations
...
...
@@ -577,10 +577,16 @@ plperl_call_handler(PG_FUNCTION_ARGS)
{
Datum
retval
;
plperl_proc_desc
*
save_prodesc
;
FunctionCallInfo
save_caller_info
;
Tuplestorestate
*
save_tuple_store
;
TupleDesc
save_tuple_desc
;
plperl_init_all
();
save_prodesc
=
plperl_current_prodesc
;
save_caller_info
=
plperl_current_caller_info
;
save_tuple_store
=
plperl_current_tuple_store
;
save_tuple_desc
=
plperl_current_tuple_desc
;
PG_TRY
();
{
...
...
@@ -592,11 +598,17 @@ plperl_call_handler(PG_FUNCTION_ARGS)
PG_CATCH
();
{
plperl_current_prodesc
=
save_prodesc
;
plperl_current_caller_info
=
save_caller_info
;
plperl_current_tuple_store
=
save_tuple_store
;
plperl_current_tuple_desc
=
save_tuple_desc
;
PG_RE_THROW
();
}
PG_END_TRY
();
plperl_current_prodesc
=
save_prodesc
;
plperl_current_caller_info
=
save_caller_info
;
plperl_current_tuple_store
=
save_tuple_store
;
plperl_current_tuple_desc
=
save_tuple_desc
;
return
retval
;
}
...
...
@@ -897,6 +909,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
SV
*
perlret
;
Datum
retval
;
ReturnSetInfo
*
rsi
;
SV
*
array_ret
=
NULL
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
ERROR
,
"could not connect to SPI manager"
);
...
...
@@ -904,9 +917,9 @@ plperl_func_handler(PG_FUNCTION_ARGS)
prodesc
=
compile_plperl_function
(
fcinfo
->
flinfo
->
fn_oid
,
false
);
plperl_current_prodesc
=
prodesc
;
p
rodesc
->
caller_info
=
fcinfo
;
p
rodesc
->
tuple_store
=
0
;
p
rodesc
->
tuple_desc
=
0
;
p
lperl_current_
caller_info
=
fcinfo
;
p
lperl_current_
tuple_store
=
0
;
p
lperl_current_
tuple_desc
=
0
;
perlret
=
plperl_call_perl_func
(
prodesc
,
fcinfo
);
...
...
@@ -958,10 +971,10 @@ plperl_func_handler(PG_FUNCTION_ARGS)
}
rsi
->
returnMode
=
SFRM_Materialize
;
if
(
p
rodesc
->
tuple_store
)
if
(
p
lperl_current_
tuple_store
)
{
rsi
->
setResult
=
p
rodesc
->
tuple_store
;
rsi
->
setDesc
=
p
rodesc
->
tuple_desc
;
rsi
->
setResult
=
p
lperl_current_
tuple_store
;
rsi
->
setDesc
=
p
lperl_current_
tuple_desc
;
}
retval
=
(
Datum
)
0
;
}
...
...
@@ -1006,7 +1019,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
{
/* Return a perl string converted to a Datum */
char
*
val
;
SV
*
array_ret
;
if
(
prodesc
->
fn_retisarray
&&
SvTYPE
(
SvRV
(
perlret
))
==
SVt_PVAV
)
...
...
@@ -1024,7 +1036,9 @@ plperl_func_handler(PG_FUNCTION_ARGS)
Int32GetDatum
(
-
1
));
}
SvREFCNT_dec
(
perlret
);
if
(
array_ret
==
NULL
)
SvREFCNT_dec
(
perlret
);
return
retval
;
}
...
...
@@ -1526,7 +1540,7 @@ void
plperl_return_next
(
SV
*
sv
)
{
plperl_proc_desc
*
prodesc
=
plperl_current_prodesc
;
FunctionCallInfo
fcinfo
=
p
rodesc
->
caller_info
;
FunctionCallInfo
fcinfo
=
p
lperl_current_
caller_info
;
ReturnSetInfo
*
rsi
=
(
ReturnSetInfo
*
)
fcinfo
->
resultinfo
;
MemoryContext
cxt
;
HeapTuple
tuple
;
...
...
@@ -1553,8 +1567,9 @@ plperl_return_next(SV *sv)
cxt
=
MemoryContextSwitchTo
(
rsi
->
econtext
->
ecxt_per_query_memory
);
if
(
!
prodesc
->
tuple_store
)
prodesc
->
tuple_store
=
tuplestore_begin_heap
(
true
,
false
,
work_mem
);
if
(
!
plperl_current_tuple_store
)
plperl_current_tuple_store
=
tuplestore_begin_heap
(
true
,
false
,
work_mem
);
if
(
prodesc
->
fn_retistuple
)
{
...
...
@@ -1590,10 +1605,10 @@ plperl_return_next(SV *sv)
tuple
=
heap_form_tuple
(
tupdesc
,
&
ret
,
&
isNull
);
}
if
(
!
p
rodesc
->
tuple_desc
)
p
rodesc
->
tuple_desc
=
tupdesc
;
if
(
!
p
lperl_current_
tuple_desc
)
p
lperl_current_
tuple_desc
=
tupdesc
;
tuplestore_puttuple
(
p
rodesc
->
tuple_store
,
tuple
);
tuplestore_puttuple
(
p
lperl_current_
tuple_store
,
tuple
);
heap_freetuple
(
tuple
);
MemoryContextSwitchTo
(
cxt
);
}
...
...
src/pl/plperl/sql/plperl.sql
View file @
220e6bfc
...
...
@@ -260,3 +260,44 @@ while (defined ($y = spi_fetchrow($x))) {
return
;
$$
LANGUAGE
plperl
;
SELECT
*
from
perl_spi_func
();
---
--- Test recursion via SPI
---
CREATE
OR
REPLACE
FUNCTION
recurse
(
i
int
)
RETURNS
SETOF
TEXT
LANGUAGE
plperl
AS
$$
my
$
i
=
shift
;
foreach
my
$
x
(
1
..
$
i
)
{
return_next
"hello $x"
;
}
if
(
$
i
>
2
)
{
my
$
z
=
$
i
-
1
;
my
$
cursor
=
spi_query
(
"select * from recurse($z)"
);
while
(
defined
(
my
$
row
=
spi_fetchrow
(
$
cursor
)))
{
return_next
"recurse $i: $row->{recurse}"
;
}
}
return
undef
;
$$
;
SELECT
*
FROM
recurse
(
2
);
SELECT
*
FROM
recurse
(
3
);
---
--- Test arrary return
---
CREATE
OR
REPLACE
FUNCTION
array_of_text
()
RETURNS
TEXT
[][]
LANGUAGE
plperl
as
$$
return
[[
'a"b'
,
'c,d'
],[
'e
\\
f'
,
'g'
]];
$$
;
SELECT
array_of_text
();
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment