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
0053cebe
Commit
0053cebe
authored
Nov 05, 2001
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix coredump in plpgsql when trying to return a rowtype result.
Need to return a TupleTableSlot, not just a bare tuple.
parent
ea08e6cd
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
206 additions
and
35 deletions
+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
No files found.
doc/src/sgml/spi.sgml
View file @
0053cebe
...
@@ -1272,6 +1272,135 @@ TBD
...
@@ -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">
<REFENTRY ID="SPI-SPIMODIFYTUPLE">
<REFMETA>
<REFMETA>
<REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE>
<REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE>
...
@@ -2695,6 +2824,7 @@ made in this context.
...
@@ -2695,6 +2824,7 @@ made in this context.
<Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility
<Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility
functions (except for <Function>SPI_copytuple</Function>,
functions (except for <Function>SPI_copytuple</Function>,
<Function>SPI_copytupledesc</Function>,
<Function>SPI_copytupledesc</Function>,
<Function>SPI_copytupleintoslot</Function>,
<Function>SPI_modifytuple</Function>,
<Function>SPI_modifytuple</Function>,
<Function>SPI_palloc</Function> and <Function>SPI_repalloc</Function>) are
<Function>SPI_palloc</Function> and <Function>SPI_repalloc</Function>) are
made in this context.
made in this context.
...
...
src/backend/executor/spi.c
View file @
0053cebe
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* 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)
...
@@ -360,6 +360,40 @@ SPI_copytupledesc(TupleDesc tupdesc)
return
ctupdesc
;
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
HeapTuple
SPI_modifytuple
(
Relation
rel
,
HeapTuple
tuple
,
int
natts
,
int
*
attnum
,
SPI_modifytuple
(
Relation
rel
,
HeapTuple
tuple
,
int
natts
,
int
*
attnum
,
Datum
*
Values
,
char
*
Nulls
)
Datum
*
Values
,
char
*
Nulls
)
...
...
src/include/executor/spi.h
View file @
0053cebe
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
*
*
* spi.h
* 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);
...
@@ -89,6 +89,8 @@ extern int SPI_freeplan(void *plan);
extern
HeapTuple
SPI_copytuple
(
HeapTuple
tuple
);
extern
HeapTuple
SPI_copytuple
(
HeapTuple
tuple
);
extern
TupleDesc
SPI_copytupledesc
(
TupleDesc
tupdesc
);
extern
TupleDesc
SPI_copytupledesc
(
TupleDesc
tupdesc
);
extern
TupleTableSlot
*
SPI_copytupleintoslot
(
HeapTuple
tuple
,
TupleDesc
tupdesc
);
extern
HeapTuple
SPI_modifytuple
(
Relation
rel
,
HeapTuple
tuple
,
int
natts
,
extern
HeapTuple
SPI_modifytuple
(
Relation
rel
,
HeapTuple
tuple
,
int
natts
,
int
*
attnum
,
Datum
*
Values
,
char
*
Nulls
);
int
*
attnum
,
Datum
*
Values
,
char
*
Nulls
);
extern
int
SPI_fnumber
(
TupleDesc
tupdesc
,
char
*
fname
);
extern
int
SPI_fnumber
(
TupleDesc
tupdesc
,
char
*
fname
);
...
...
src/pl/plpgsql/src/pl_exec.c
View file @
0053cebe
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
* procedural language
* procedural language
*
*
* IDENTIFICATION
* 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.
* This software is copyrighted by Jan Wieck - Hamburg.
*
*
...
@@ -400,32 +400,43 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
...
@@ -400,32 +400,43 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
fcinfo
->
isnull
=
estate
.
retisnull
;
fcinfo
->
isnull
=
estate
.
retisnull
;
if
(
!
estate
.
retis
tuple
)
if
(
!
estate
.
retis
null
)
{
{
estate
.
retval
=
exec_cast_value
(
estate
.
retval
,
estate
.
rettype
,
if
(
estate
.
retistuple
)
func
->
fn_rettype
,
{
&
(
func
->
fn_retinput
),
/* Copy tuple to upper executor memory */
func
->
fn_rettypelem
,
/* Here we need to return a TupleTableSlot not just a tuple */
-
1
,
estate
.
retval
=
(
Datum
)
&
fcinfo
->
isnull
);
SPI_copytupleintoslot
((
HeapTuple
)
(
estate
.
retval
),
estate
.
rettupdesc
);
/*
}
* If the functions return type isn't by value, copy the value
else
* into upper executor memory context.
*/
if
(
!
fcinfo
->
isnull
&&
!
func
->
fn_retbyval
)
{
{
int
len
;
/* Cast value to proper type */
Datum
tmp
;
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
)
if
(
func
->
fn_rettyplen
<
0
)
len
=
VARSIZE
(
estate
.
retval
);
len
=
VARSIZE
(
estate
.
retval
);
else
else
len
=
func
->
fn_rettyplen
;
len
=
func
->
fn_rettyplen
;
tmp
=
(
Datum
)
SPI_palloc
(
len
);
tmp
=
(
Datum
)
SPI_palloc
(
len
);
memcpy
((
void
*
)
tmp
,
(
void
*
)
estate
.
retval
,
len
);
memcpy
((
void
*
)
tmp
,
(
void
*
)
estate
.
retval
,
len
);
estate
.
retval
=
tmp
;
estate
.
retval
=
tmp
;
}
}
}
}
}
...
@@ -1619,8 +1630,8 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
...
@@ -1619,8 +1630,8 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
if
(
HeapTupleIsValid
(
rec
->
tup
))
if
(
HeapTupleIsValid
(
rec
->
tup
))
{
{
estate
->
retval
=
(
Datum
)
SPI_copytuple
(
rec
->
tup
)
;
estate
->
retval
=
(
Datum
)
rec
->
tup
;
estate
->
rettupdesc
=
SPI_copytupledesc
(
rec
->
tupdesc
)
;
estate
->
rettupdesc
=
rec
->
tupdesc
;
estate
->
retisnull
=
false
;
estate
->
retisnull
=
false
;
}
}
return
PLPGSQL_RC_RETURN
;
return
PLPGSQL_RC_RETURN
;
...
@@ -1631,16 +1642,10 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
...
@@ -1631,16 +1642,10 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
exec_run_select
(
estate
,
stmt
->
expr
,
1
,
NULL
);
exec_run_select
(
estate
,
stmt
->
expr
,
1
,
NULL
);
if
(
estate
->
eval_processed
>
0
)
if
(
estate
->
eval_processed
>
0
)
{
{
estate
->
retval
=
(
Datum
)
SPI_copytuple
(
estate
->
eval_tuptable
->
vals
[
0
])
;
estate
->
retval
=
(
Datum
)
estate
->
eval_tuptable
->
vals
[
0
]
;
estate
->
rettupdesc
=
SPI_copytupledesc
(
estate
->
eval_tuptable
->
tupdesc
)
;
estate
->
rettupdesc
=
estate
->
eval_tuptable
->
tupdesc
;
estate
->
retisnull
=
false
;
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
;
return
PLPGSQL_RC_RETURN
;
}
}
...
...
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