Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
220e6bfc
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
220e6bfc
编写于
7月 12, 2005
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix plperl to do recursion safely, and fix a problem with array results.
Add suitable regression tests. Andrew Dunstan
上级
a1a64bb7
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
128 addition
and
19 deletion
+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
未找到文件。
src/pl/plperl/expected/plperl.out
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
();
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录