Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
0053cebe
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,发现更多精彩内容 >>
提交
0053cebe
编写于
11月 05, 2001
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix coredump in plpgsql when trying to return a rowtype result.
Need to return a TupleTableSlot, not just a bare tuple.
上级
ea08e6cd
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
206 addition
and
35 deletion
+206
-35
doc/src/sgml/spi.sgml
doc/src/sgml/spi.sgml
+130
-0
src/backend/executor/spi.c
src/backend/executor/spi.c
+35
-1
src/include/executor/spi.h
src/include/executor/spi.h
+3
-1
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/pl_exec.c
+38
-33
未找到文件。
doc/src/sgml/spi.sgml
浏览文件 @
0053cebe
...
...
@@ -1272,6 +1272,135 @@ TBD
<!-- *********************************************** -->
<!-- *********************************************** -->
<REFENTRY ID="SPI-SPICOPYTUPLEINTOSLOT">
<REFMETA>
<REFENTRYTITLE>SPI_copytupleintoslot</REFENTRYTITLE>
<REFMISCINFO>SPI - Tuple and Descriptor Copy</REFMISCINFO>
</REFMETA>
<REFNAMEDIV>
<REFNAME>SPI_copytupleintoslot
</REFNAME>
<REFPURPOSE>
Makes copy of tuple and descriptor in upper Executor context
</REFPURPOSE>
<INDEXTERM ID="IX-SPI-SPICOPYTUPLEINTOSLOT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM>
<INDEXTERM ID="IX-SPI-SPICOPYTUPLEINTOSLOT-2"><PRIMARY>SPI_copytupleintoslot</PRIMARY></INDEXTERM>
</REFNAMEDIV>
<REFSYNOPSISDIV>
<REFSYNOPSISDIVINFO>
<DATE>1997-12-24</DATE>
</REFSYNOPSISDIVINFO>
<SYNOPSIS>
SPI_copytupleintoslot(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>)
</SYNOPSIS>
<REFSECT2 ID="R2-SPI-SPICOPYTUPLEINTOSLOT-1">
<REFSECT2INFO>
<DATE>1997-12-24</DATE>
</REFSECT2INFO>
<TITLE>Inputs
</TITLE>
<VARIABLELIST>
<VARLISTENTRY>
<TERM>
HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
</TERM>
<LISTITEM>
<PARA>
Input tuple to be copied
</PARA>
</LISTITEM>
</VARLISTENTRY>
<VARLISTENTRY>
<TERM>
TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
</TERM>
<LISTITEM>
<PARA>
Input tuple descriptor to be copied
</PARA>
</LISTITEM>
</VARLISTENTRY>
</VARIABLELIST>
</REFSECT2>
<REFSECT2 ID="R2-SPI-SPICOPYTUPLEINTOSLOT-2">
<REFSECT2INFO>
<DATE>1997-12-24</DATE>
</REFSECT2INFO>
<TITLE>Outputs
</TITLE>
<VARIABLELIST>
<VARLISTENTRY>
<TERM>
TupleTableSlot *
</TERM>
<LISTITEM>
<PARA>
Tuple slot containing copied tuple and descriptor
<SimpleList>
<Member>
<ReturnValue>non-NULL</ReturnValue>
if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
and <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
are not NULL and the copy was successful
</Member>
<Member>
<ReturnValue>NULL</ReturnValue>
only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
or <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
is NULL
</Member>
</SimpleList>
</para>
</LISTITEM>
</VARLISTENTRY>
</VARIABLELIST>
</REFSECT2>
</REFSYNOPSISDIV>
<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-1">
<REFSECT1INFO>
<DATE>1997-12-24</DATE>
</REFSECT1INFO>
<TITLE>Description
</TITLE>
<PARA>
<FUNCTION>SPI_copytupleintoslot</FUNCTION>
makes a copy of tuple in upper Executor context, returning it in the
form of a filled-in TupleTableSlot.
See the section on Memory Management.
</PARA>
</REFSECT1>
<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-2">
<TITLE>Usage
</TITLE>
<Para>
TBD
</PARA>
</REFSECT1>
<!--
<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-3">
<TITLE>Algorithm
</TITLE>
<PARA>
</PARA>
</REFSECT1>
-->
<!--
<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-4">
<TITLE>Structures
</TITLE>
<PARA>None
</PARA>
</REFSECT1>
-->
</REFENTRY>
<!-- *********************************************** -->
<!-- *********************************************** -->
<!-- *********************************************** -->
<REFENTRY ID="SPI-SPIMODIFYTUPLE">
<REFMETA>
<REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE>
...
...
@@ -2695,6 +2824,7 @@ made in this context.
<Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility
functions (except for <Function>SPI_copytuple</Function>,
<Function>SPI_copytupledesc</Function>,
<Function>SPI_copytupleintoslot</Function>,
<Function>SPI_modifytuple</Function>,
<Function>SPI_palloc</Function> and <Function>SPI_repalloc</Function>) are
made in this context.
...
...
src/backend/executor/spi.c
浏览文件 @
0053cebe
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.6
0 2001/10/25 05:49:29 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.6
1 2001/11/05 19:41:56 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -360,6 +360,40 @@ SPI_copytupledesc(TupleDesc tupdesc)
return
ctupdesc
;
}
TupleTableSlot
*
SPI_copytupleintoslot
(
HeapTuple
tuple
,
TupleDesc
tupdesc
)
{
MemoryContext
oldcxt
=
NULL
;
TupleTableSlot
*
cslot
;
HeapTuple
ctuple
;
TupleDesc
ctupdesc
;
if
(
tuple
==
NULL
||
tupdesc
==
NULL
)
{
SPI_result
=
SPI_ERROR_ARGUMENT
;
return
NULL
;
}
if
(
_SPI_curid
+
1
==
_SPI_connected
)
/* connected */
{
if
(
_SPI_current
!=
&
(
_SPI_stack
[
_SPI_curid
+
1
]))
elog
(
FATAL
,
"SPI: stack corrupted"
);
oldcxt
=
MemoryContextSwitchTo
(
_SPI_current
->
savedcxt
);
}
ctuple
=
heap_copytuple
(
tuple
);
ctupdesc
=
CreateTupleDescCopy
(
tupdesc
);
cslot
=
MakeTupleTableSlot
();
ExecSetSlotDescriptor
(
cslot
,
ctupdesc
,
true
);
cslot
=
ExecStoreTuple
(
ctuple
,
cslot
,
InvalidBuffer
,
true
);
if
(
oldcxt
)
MemoryContextSwitchTo
(
oldcxt
);
return
cslot
;
}
HeapTuple
SPI_modifytuple
(
Relation
rel
,
HeapTuple
tuple
,
int
natts
,
int
*
attnum
,
Datum
*
Values
,
char
*
Nulls
)
...
...
src/include/executor/spi.h
浏览文件 @
0053cebe
...
...
@@ -2,7 +2,7 @@
*
* spi.h
*
* $Id: spi.h,v 1.3
1 2001/11/05 17:46:33 momjian
Exp $
* $Id: spi.h,v 1.3
2 2001/11/05 19:41:56 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -89,6 +89,8 @@ extern int SPI_freeplan(void *plan);
extern
HeapTuple
SPI_copytuple
(
HeapTuple
tuple
);
extern
TupleDesc
SPI_copytupledesc
(
TupleDesc
tupdesc
);
extern
TupleTableSlot
*
SPI_copytupleintoslot
(
HeapTuple
tuple
,
TupleDesc
tupdesc
);
extern
HeapTuple
SPI_modifytuple
(
Relation
rel
,
HeapTuple
tuple
,
int
natts
,
int
*
attnum
,
Datum
*
Values
,
char
*
Nulls
);
extern
int
SPI_fnumber
(
TupleDesc
tupdesc
,
char
*
fname
);
...
...
src/pl/plpgsql/src/pl_exec.c
浏览文件 @
0053cebe
...
...
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.4
8 2001/10/25 05:50:20 momjian
Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.4
9 2001/11/05 19:41:56 tgl
Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
...
...
@@ -400,32 +400,43 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
fcinfo
->
isnull
=
estate
.
retisnull
;
if
(
!
estate
.
retis
tuple
)
if
(
!
estate
.
retis
null
)
{
estate
.
retval
=
exec_cast_value
(
estate
.
retval
,
estate
.
rettype
,
func
->
fn_rettype
,
&
(
func
->
fn_retinput
),
func
->
fn_rettypelem
,
-
1
,
&
fcinfo
->
isnull
);
/*
* If the functions return type isn't by value, copy the value
* into upper executor memory context.
*/
if
(
!
fcinfo
->
isnull
&&
!
func
->
fn_retbyval
)
if
(
estate
.
retistuple
)
{
/* Copy tuple to upper executor memory */
/* Here we need to return a TupleTableSlot not just a tuple */
estate
.
retval
=
(
Datum
)
SPI_copytupleintoslot
((
HeapTuple
)
(
estate
.
retval
),
estate
.
rettupdesc
);
}
else
{
int
len
;
Datum
tmp
;
/* Cast value to proper type */
estate
.
retval
=
exec_cast_value
(
estate
.
retval
,
estate
.
rettype
,
func
->
fn_rettype
,
&
(
func
->
fn_retinput
),
func
->
fn_rettypelem
,
-
1
,
&
fcinfo
->
isnull
);
/*
* If the functions return type isn't by value, copy the value
* into upper executor memory context.
*/
if
(
!
fcinfo
->
isnull
&&
!
func
->
fn_retbyval
)
{
int
len
;
Datum
tmp
;
if
(
func
->
fn_rettyplen
<
0
)
len
=
VARSIZE
(
estate
.
retval
);
else
len
=
func
->
fn_rettyplen
;
if
(
func
->
fn_rettyplen
<
0
)
len
=
VARSIZE
(
estate
.
retval
);
else
len
=
func
->
fn_rettyplen
;
tmp
=
(
Datum
)
SPI_palloc
(
len
);
memcpy
((
void
*
)
tmp
,
(
void
*
)
estate
.
retval
,
len
);
estate
.
retval
=
tmp
;
tmp
=
(
Datum
)
SPI_palloc
(
len
);
memcpy
((
void
*
)
tmp
,
(
void
*
)
estate
.
retval
,
len
);
estate
.
retval
=
tmp
;
}
}
}
...
...
@@ -1619,8 +1630,8 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
if
(
HeapTupleIsValid
(
rec
->
tup
))
{
estate
->
retval
=
(
Datum
)
SPI_copytuple
(
rec
->
tup
)
;
estate
->
rettupdesc
=
SPI_copytupledesc
(
rec
->
tupdesc
)
;
estate
->
retval
=
(
Datum
)
rec
->
tup
;
estate
->
rettupdesc
=
rec
->
tupdesc
;
estate
->
retisnull
=
false
;
}
return
PLPGSQL_RC_RETURN
;
...
...
@@ -1631,16 +1642,10 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
exec_run_select
(
estate
,
stmt
->
expr
,
1
,
NULL
);
if
(
estate
->
eval_processed
>
0
)
{
estate
->
retval
=
(
Datum
)
SPI_copytuple
(
estate
->
eval_tuptable
->
vals
[
0
])
;
estate
->
rettupdesc
=
SPI_copytupledesc
(
estate
->
eval_tuptable
->
tupdesc
)
;
estate
->
retval
=
(
Datum
)
estate
->
eval_tuptable
->
vals
[
0
]
;
estate
->
rettupdesc
=
estate
->
eval_tuptable
->
tupdesc
;
estate
->
retisnull
=
false
;
}
/*
* Okay to clean up here, since we already copied result tuple
* to upper executor.
*/
exec_eval_cleanup
(
estate
);
}
return
PLPGSQL_RC_RETURN
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录