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
bf1d9aeb
Commit
bf1d9aeb
authored
Sep 06, 1997
by
Vadim B. Mikheev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanups.
parent
5d68d3e9
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
348 additions
and
602 deletions
+348
-602
src/backend/executor/spi.c
src/backend/executor/spi.c
+342
-587
src/include/executor/spi.h
src/include/executor/spi.h
+6
-15
No files found.
src/backend/executor/spi.c
View file @
bf1d9aeb
...
...
@@ -9,31 +9,6 @@
#include "access/printtup.h"
#include "fmgr.h"
typedef
struct
{
QueryTreeList
*
qtlist
;
List
*
ptlist
;
int
nargs
;
Oid
*
argtypes
;
}
_SPI_plan
;
typedef
struct
{
int
len
;
void
*
data
;
}
_SPI_data
;
typedef
struct
{
char
*
ident
;
int
plcnt
;
_SPI_plan
**
plan
;
int
dtcnt
;
_SPI_data
*
data
;
}
_SPI_entry
;
static
_SPI_entry
*
_SPI_xtab
=
NULL
;
static
int
_SPI_xtabsz
=
0
;
static
_SPI_entry
*
_SPI_stab
=
NULL
;
static
int
_SPI_stabsz
=
0
;
typedef
struct
{
QueryTreeList
*
qtlist
;
/* malloced */
uint32
processed
;
/* by Executor */
...
...
@@ -41,7 +16,6 @@ typedef struct {
Portal
portal
;
/* portal per procedure */
MemoryContext
savedcxt
;
CommandId
savedId
;
_SPI_entry
ltab
;
}
_SPI_connection
;
static
Portal
_SPI_portal
=
(
Portal
)
NULL
;
...
...
@@ -52,10 +26,17 @@ static int _SPI_curid = -1;
uint32
SPI_processed
=
0
;
SPITupleTable
*
SPI_tuptable
;
int
SPI_
error
;
int
SPI_
result
;
void
spi_printtup
(
HeapTuple
tuple
,
TupleDesc
tupdesc
);
typedef
struct
{
QueryTreeList
*
qtlist
;
List
*
ptlist
;
int
nargs
;
Oid
*
argtypes
;
}
_SPI_plan
;
static
int
_SPI_execute
(
char
*
src
,
int
tcount
,
_SPI_plan
*
plan
);
static
int
_SPI_pquery
(
QueryDesc
*
queryDesc
,
EState
*
state
,
int
tcount
);
#if 0
...
...
@@ -64,7 +45,7 @@ static void _SPI_fetch (FetchStmt *stmt);
static
int
_SPI_execute_plan
(
_SPI_plan
*
plan
,
char
**
Values
,
char
*
Nulls
,
int
tcount
);
static
int
_SPI_copy_plan
(
int
dspace
,
_SPI_plan
*
plan
);
static
_SPI_plan
*
_SPI_copy_plan
(
_SPI_plan
*
plan
,
bool
local
);
static
int
_SPI_begin_call
(
bool
execmem
);
static
int
_SPI_end_call
(
bool
procmem
);
...
...
@@ -79,14 +60,11 @@ extern void ShowUsage (void);
#endif
int
SPI_connect
(
char
*
ident
)
SPI_connect
()
{
char
pname
[
64
];
PortalVariableMemory
pvmem
;
if
(
!
ident
||
*
ident
==
0
)
return
(
SPI_ERROR_ARGUMENT
);
/*
* It's possible on startup and after commit/abort.
* In future we'll catch commit/abort in some way...
...
...
@@ -99,8 +77,6 @@ SPI_connect (char *ident)
free
(
_SPI_stack
);
_SPI_current
=
_SPI_stack
=
NULL
;
_SPI_connected
=
_SPI_curid
=
-
1
;
_SPI_xtab
=
NULL
;
_SPI_xtabsz
=
0
;
SPI_processed
=
0
;
SPI_tuptable
=
NULL
;
_SPI_portal
=
CreatePortal
(
pname
);
...
...
@@ -151,10 +127,6 @@ SPI_connect (char *ident)
_SPI_current
->
savedId
=
GetScanCommandId
();
SetScanCommandId
(
GetCurrentCommandId
());
_SPI_current
->
ltab
.
ident
=
pstrdup
(
ident
);
_SPI_current
->
ltab
.
plcnt
=
0
;
_SPI_current
->
ltab
.
dtcnt
=
0
;
return
(
SPI_OK_CONNECT
);
}
...
...
@@ -198,65 +170,285 @@ SPI_finish ()
}
int
SPI_exec
(
char
*
src
)
SPI_exec
(
char
*
src
,
int
tcount
)
{
int
res
;
if
(
src
==
NULL
||
tcount
<
0
)
return
(
SPI_ERROR_ARGUMENT
);
res
=
_SPI_begin_call
(
true
);
if
(
res
<
0
)
return
(
res
);
res
=
_SPI_execute
(
src
,
0
,
NULL
);
res
=
_SPI_execute
(
src
,
tcount
,
NULL
);
_SPI_end_call
(
true
);
return
(
res
);
}
int
SPI_exec
n
(
char
*
src
,
int
tcount
)
SPI_exec
p
(
void
*
plan
,
char
**
Values
,
char
*
Nulls
,
int
tcount
)
{
int
res
;
if
(
tcount
<
0
)
if
(
plan
==
NULL
||
tcount
<
0
)
return
(
SPI_ERROR_ARGUMENT
);
if
(
((
_SPI_plan
*
)
plan
)
->
nargs
>
0
&&
(
Values
==
NULL
||
Nulls
==
NULL
)
)
return
(
SPI_ERROR_PARAM
);
res
=
_SPI_begin_call
(
true
);
if
(
res
<
0
)
return
(
res
);
res
=
_SPI_execute
(
src
,
tcount
,
NULL
);
res
=
_SPI_execute
_plan
((
_SPI_plan
*
)
plan
,
Values
,
Nulls
,
tcount
);
_SPI_end_call
(
true
);
return
(
res
);
}
int
void
*
SPI_prepare
(
char
*
src
,
int
nargs
,
Oid
*
argtypes
)
{
_SPI_plan
*
plan
;
int
res
;
if
(
nargs
<
0
||
(
nargs
>
0
&&
argtypes
==
NULL
)
)
return
(
SPI_ERROR_ARGUMENT
);
{
SPI_result
=
SPI_ERROR_ARGUMENT
;
return
(
NULL
);
}
res
=
_SPI_begin_call
(
true
);
if
(
res
<
0
)
return
(
res
);
SPI_result
=
_SPI_begin_call
(
true
);
if
(
SPI_result
<
0
)
return
(
NULL
);
plan
=
(
_SPI_plan
*
)
palloc
(
sizeof
(
_SPI_plan
));
plan
=
(
_SPI_plan
*
)
palloc
(
sizeof
(
_SPI_plan
));
/* Executor context */
plan
->
argtypes
=
argtypes
;
plan
->
nargs
=
nargs
;
res
=
_SPI_execute
(
src
,
0
,
plan
);
SPI_result
=
_SPI_execute
(
src
,
0
,
plan
);
if
(
res
>=
0
)
/* copy plan to local data space */
res
=
_SPI_copy_plan
(
SPI_DSPACE_LOCAL
,
plan
);
if
(
SPI_result
>=
0
)
/* copy plan to local space */
plan
=
_SPI_copy_plan
(
plan
,
true
);
else
plan
=
NULL
;
_SPI_end_call
(
true
);
return
(
res
);
return
((
void
*
)
plan
);
}
void
*
SPI_saveplan
(
void
*
plan
)
{
_SPI_plan
*
newplan
;
if
(
plan
==
NULL
)
{
SPI_result
=
SPI_ERROR_ARGUMENT
;
return
(
NULL
);
}
SPI_result
=
_SPI_begin_call
(
false
);
/* don't change context */
if
(
SPI_result
<
0
)
return
(
NULL
);
newplan
=
_SPI_copy_plan
((
_SPI_plan
*
)
plan
,
false
);
_SPI_curid
--
;
SPI_result
=
0
;
return
((
void
*
)
newplan
);
}
int
SPI_fnumber
(
TupleDesc
tupdesc
,
char
*
fname
)
{
int
res
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
return
(
SPI_ERROR_UNCONNECTED
);
for
(
res
=
0
;
res
<
tupdesc
->
natts
;
res
++
)
{
if
(
strcmp
(
tupdesc
->
attrs
[
res
]
->
attname
.
data
,
fname
)
==
0
)
return
(
res
+
1
);
}
return
(
SPI_ERROR_NOATTRIBUTE
);
}
char
*
SPI_getvalue
(
HeapTuple
tuple
,
TupleDesc
tupdesc
,
int
fnumber
)
{
char
*
val
;
bool
isnull
;
Oid
foutoid
;
SPI_result
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_result
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
if
(
tuple
->
t_natts
<
fnumber
||
fnumber
<=
0
)
return
(
NULL
);
val
=
heap_getattr
(
tuple
,
InvalidBuffer
,
fnumber
,
tupdesc
,
&
isnull
);
if
(
isnull
)
return
(
NULL
);
foutoid
=
typtoout
((
Oid
)
tupdesc
->
attrs
[
fnumber
-
1
]
->
atttypid
);
if
(
!
OidIsValid
(
foutoid
)
)
{
SPI_result
=
SPI_ERROR_NOOUTFUNC
;
return
(
NULL
);
}
return
(
fmgr
(
foutoid
,
val
,
gettypelem
(
tupdesc
->
attrs
[
fnumber
-
1
]
->
atttypid
)));
}
char
*
SPI_getbinval
(
HeapTuple
tuple
,
TupleDesc
tupdesc
,
int
fnumber
,
bool
*
isnull
)
{
char
*
val
;
*
isnull
=
true
;
SPI_result
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_result
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
if
(
tuple
->
t_natts
<
fnumber
||
fnumber
<=
0
)
return
(
NULL
);
val
=
heap_getattr
(
tuple
,
InvalidBuffer
,
fnumber
,
tupdesc
,
isnull
);
return
(
val
);
}
char
*
SPI_gettype
(
TupleDesc
tupdesc
,
int
fnumber
)
{
HeapTuple
typeTuple
;
SPI_result
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_result
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
if
(
tupdesc
->
natts
<
fnumber
||
fnumber
<=
0
)
{
SPI_result
=
SPI_ERROR_NOATTRIBUTE
;
return
(
NULL
);
}
typeTuple
=
SearchSysCacheTuple
(
TYPOID
,
ObjectIdGetDatum
(
tupdesc
->
attrs
[
fnumber
-
1
]
->
atttypid
),
0
,
0
,
0
);
if
(
!
HeapTupleIsValid
(
typeTuple
)
)
{
SPI_result
=
SPI_ERROR_TYPUNKNOWN
;
return
(
NULL
);
}
return
(
pstrdup
(((
TypeTupleForm
)
GETSTRUCT
(
typeTuple
))
->
typname
.
data
));
}
Oid
SPI_gettypeid
(
TupleDesc
tupdesc
,
int
fnumber
)
{
SPI_result
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_result
=
SPI_ERROR_UNCONNECTED
;
return
(
InvalidOid
);
}
if
(
tupdesc
->
natts
<
fnumber
||
fnumber
<=
0
)
{
SPI_result
=
SPI_ERROR_NOATTRIBUTE
;
return
(
InvalidOid
);
}
return
(
tupdesc
->
attrs
[
fnumber
-
1
]
->
atttypid
);
}
char
*
SPI_getrelname
(
Relation
rel
)
{
SPI_result
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_result
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
return
(
pstrdup
(
rel
->
rd_rel
->
relname
.
data
));
}
/*
* spi_printtup --
* store tuple retrieved by Executor into SPITupleTable
* of current SPI procedure
*
*/
void
spi_printtup
(
HeapTuple
tuple
,
TupleDesc
tupdesc
)
{
SPITupleTable
*
tuptable
;
MemoryContext
oldcxt
;
/*
* When called by Executor _SPI_curid expected to be
* equal to _SPI_connected
*/
if
(
_SPI_curid
!=
_SPI_connected
||
_SPI_connected
<
0
)
elog
(
FATAL
,
"SPI: improper call to spi_printtup"
);
if
(
_SPI_current
!=
&
(
_SPI_stack
[
_SPI_curid
])
)
elog
(
FATAL
,
"SPI: stack corrupted in spi_printtup"
);
oldcxt
=
_SPI_procmem
();
/* switch to procedure memory context */
tuptable
=
_SPI_current
->
tuptable
;
if
(
tuptable
==
NULL
)
{
_SPI_current
->
tuptable
=
tuptable
=
(
SPITupleTable
*
)
palloc
(
sizeof
(
SPITupleTable
));
tuptable
->
alloced
=
tuptable
->
free
=
128
;
tuptable
->
vals
=
(
HeapTuple
*
)
palloc
(
tuptable
->
alloced
*
sizeof
(
HeapTuple
));
tuptable
->
tupdesc
=
CreateTupleDescCopy
(
tupdesc
);
}
else
if
(
tuptable
->
free
==
0
)
{
tuptable
->
free
=
256
;
tuptable
->
alloced
+=
tuptable
->
free
;
tuptable
->
vals
=
(
HeapTuple
*
)
repalloc
(
tuptable
->
vals
,
tuptable
->
alloced
*
sizeof
(
HeapTuple
));
}
tuptable
->
vals
[
tuptable
->
alloced
-
tuptable
->
free
]
=
heap_copytuple
(
tuple
);
(
tuptable
->
free
)
--
;
MemoryContextSwitchTo
(
oldcxt
);
return
;
}
/*
* Static functions
*/
static
int
_SPI_execute
(
char
*
src
,
int
tcount
,
_SPI_plan
*
plan
)
{
...
...
@@ -355,34 +547,103 @@ _SPI_execute (char *src, int tcount, _SPI_plan *plan)
}
static
int
_SPI_
pquery
(
QueryDesc
*
queryDesc
,
EState
*
state
,
int
tcount
)
_SPI_
execute_plan
(
_SPI_plan
*
plan
,
char
**
Values
,
char
*
Nulls
,
int
tcount
)
{
Query
*
parseTree
;
Plan
*
plan
;
int
operation
;
TupleDesc
tupdesc
;
bool
isRetrieveIntoPortal
=
false
;
bool
isRetrieveIntoRelation
=
false
;
char
*
intoName
=
NULL
;
QueryTreeList
*
queryTree_list
=
plan
->
qtlist
;
List
*
planTree_list
=
plan
->
ptlist
;
QueryDesc
*
qdesc
;
Query
*
queryTree
;
Plan
*
planTree
;
EState
*
state
;
int
nargs
=
plan
->
nargs
;
int
qlen
=
queryTree_list
->
len
;
int
res
;
int
i
,
k
;
parseTree
=
queryDesc
->
parsetree
;
plan
=
queryDesc
->
plantree
;
operation
=
queryDesc
->
operation
;
/* Increment CommandCounter to see changes made by now */
CommandCounterIncrement
();
switch
(
operation
)
{
case
CMD_SELECT
:
res
=
SPI_OK_SELECT
;
if
(
parseTree
->
isPortal
)
SPI_processed
=
0
;
SPI_tuptable
=
NULL
;
_SPI_current
->
tuptable
=
NULL
;
_SPI_current
->
qtlist
=
NULL
;
for
(
i
=
0
;
;
i
++
)
{
isRetrieveIntoPortal
=
true
;
intoName
=
parseTree
->
into
;
parseTree
->
isBinary
=
false
;
/* */
queryTree
=
(
Query
*
)
(
queryTree_list
->
qtrees
[
i
]);
planTree
=
lfirst
(
planTree_list
);
return
(
SPI_ERROR_CURSOR
);
planTree_list
=
lnext
(
planTree_list
);
}
if
(
queryTree
->
commandType
==
CMD_UTILITY
)
{
ProcessUtility
(
queryTree
->
utilityStmt
,
None
);
if
(
i
<
qlen
-
1
)
CommandCounterIncrement
();
else
return
(
SPI_OK_UTILITY
);
}
else
{
qdesc
=
CreateQueryDesc
(
queryTree
,
planTree
,
(
i
<
qlen
-
1
)
?
None
:
SPI
);
state
=
CreateExecutorState
();
if
(
nargs
>
0
)
{
ParamListInfo
paramLI
=
(
ParamListInfo
)
palloc
((
nargs
+
1
)
*
sizeof
(
ParamListInfoData
));
state
->
es_param_list_info
=
paramLI
;
for
(
k
=
0
;
k
<
plan
->
nargs
;
paramLI
++
,
k
++
)
{
paramLI
->
kind
=
PARAM_NUM
;
paramLI
->
id
=
k
+
1
;
paramLI
->
isnull
=
(
Nulls
[
k
]
!=
0
);
paramLI
->
value
=
(
Datum
)
Values
[
k
];
}
paramLI
->
kind
=
PARAM_INVALID
;
}
else
state
->
es_param_list_info
=
NULL
;
res
=
_SPI_pquery
(
qdesc
,
state
,
(
i
<
qlen
-
1
)
?
0
:
tcount
);
if
(
res
<
0
||
i
>=
qlen
-
1
)
return
(
res
);
CommandCounterIncrement
();
}
}
return
(
res
);
}
static
int
_SPI_pquery
(
QueryDesc
*
queryDesc
,
EState
*
state
,
int
tcount
)
{
Query
*
parseTree
;
Plan
*
plan
;
int
operation
;
TupleDesc
tupdesc
;
bool
isRetrieveIntoPortal
=
false
;
bool
isRetrieveIntoRelation
=
false
;
char
*
intoName
=
NULL
;
int
res
;
parseTree
=
queryDesc
->
parsetree
;
plan
=
queryDesc
->
plantree
;
operation
=
queryDesc
->
operation
;
switch
(
operation
)
{
case
CMD_SELECT
:
res
=
SPI_OK_SELECT
;
if
(
parseTree
->
isPortal
)
{
isRetrieveIntoPortal
=
true
;
intoName
=
parseTree
->
into
;
parseTree
->
isBinary
=
false
;
/* */
return
(
SPI_ERROR_CURSOR
);
}
else
if
(
parseTree
->
into
!=
NULL
)
/* select into table */
{
res
=
SPI_OK_SELINTO
;
...
...
@@ -489,53 +750,6 @@ _SPI_fetch (FetchStmt *stmt)
}
#endif
/*
* spi_printtup --
* store tuple retrieved by Executor into SPITupleTable
* of current SPI procedure
*
*/
void
spi_printtup
(
HeapTuple
tuple
,
TupleDesc
tupdesc
)
{
SPITupleTable
*
tuptable
;
MemoryContext
oldcxt
;
/*
* When called by Executor _SPI_curid expected to be
* equal to _SPI_connected
*/
if
(
_SPI_curid
!=
_SPI_connected
||
_SPI_connected
<
0
)
elog
(
FATAL
,
"SPI: improper call to spi_printtup"
);
if
(
_SPI_current
!=
&
(
_SPI_stack
[
_SPI_curid
])
)
elog
(
FATAL
,
"SPI: stack corrupted in spi_printtup"
);
oldcxt
=
_SPI_procmem
();
/* switch to procedure memory context */
tuptable
=
_SPI_current
->
tuptable
;
if
(
tuptable
==
NULL
)
{
_SPI_current
->
tuptable
=
tuptable
=
(
SPITupleTable
*
)
palloc
(
sizeof
(
SPITupleTable
));
tuptable
->
alloced
=
tuptable
->
free
=
128
;
tuptable
->
vals
=
(
HeapTuple
*
)
palloc
(
tuptable
->
alloced
*
sizeof
(
HeapTuple
));
tuptable
->
tupdesc
=
CreateTupleDescCopy
(
tupdesc
);
}
else
if
(
tuptable
->
free
==
0
)
{
tuptable
->
free
=
256
;
tuptable
->
alloced
+=
tuptable
->
free
;
tuptable
->
vals
=
(
HeapTuple
*
)
repalloc
(
tuptable
->
vals
,
tuptable
->
alloced
*
sizeof
(
HeapTuple
));
}
tuptable
->
vals
[
tuptable
->
alloced
-
tuptable
->
free
]
=
heap_copytuple
(
tuple
);
(
tuptable
->
free
)
--
;
MemoryContextSwitchTo
(
oldcxt
);
return
;
}
static
MemoryContext
_SPI_execmem
()
{
...
...
@@ -636,209 +850,20 @@ _SPI_checktuples (bool isRetrieveIntoRelation)
return
(
failed
);
}
int
SPI_fnumber
(
TupleDesc
tupdesc
,
char
*
fname
)
{
int
res
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
return
(
SPI_ERROR_UNCONNECTED
);
for
(
res
=
0
;
res
<
tupdesc
->
natts
;
res
++
)
{
if
(
strcmp
(
tupdesc
->
attrs
[
res
]
->
attname
.
data
,
fname
)
==
0
)
return
(
res
);
}
return
(
SPI_ERROR_NOATTRIBUTE
);
}
char
*
SPI_getvalue
(
HeapTuple
tuple
,
TupleDesc
tupdesc
,
int
fnumber
)
{
char
*
val
;
bool
isnull
;
Oid
foutoid
;
SPI_error
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_error
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
if
(
tuple
->
t_natts
<=
fnumber
||
fnumber
<
0
)
return
(
NULL
);
val
=
heap_getattr
(
tuple
,
InvalidBuffer
,
fnumber
+
1
,
tupdesc
,
&
isnull
);
if
(
isnull
)
return
(
NULL
);
foutoid
=
typtoout
((
Oid
)
tupdesc
->
attrs
[
fnumber
]
->
atttypid
);
if
(
!
OidIsValid
(
foutoid
)
)
{
SPI_error
=
SPI_ERROR_NOOUTFUNC
;
return
(
NULL
);
}
return
(
fmgr
(
foutoid
,
val
,
gettypelem
(
tupdesc
->
attrs
[
fnumber
]
->
atttypid
)));
}
char
*
SPI_getbinval
(
HeapTuple
tuple
,
TupleDesc
tupdesc
,
int
fnumber
,
bool
*
isnull
)
{
char
*
val
;
*
isnull
=
true
;
SPI_error
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_error
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
if
(
tuple
->
t_natts
<=
fnumber
||
fnumber
<
0
)
return
(
NULL
);
val
=
heap_getattr
(
tuple
,
InvalidBuffer
,
fnumber
+
1
,
tupdesc
,
isnull
);
return
(
val
);
}
char
*
SPI_gettype
(
TupleDesc
tupdesc
,
int
fnumber
)
{
HeapTuple
typeTuple
;
SPI_error
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_error
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
if
(
tupdesc
->
natts
<=
fnumber
||
fnumber
<
0
)
return
(
NULL
);
typeTuple
=
SearchSysCacheTuple
(
TYPOID
,
ObjectIdGetDatum
(
tupdesc
->
attrs
[
fnumber
]
->
atttypid
),
0
,
0
,
0
);
if
(
!
HeapTupleIsValid
(
typeTuple
)
)
{
SPI_error
=
SPI_ERROR_TYPUNKNOWN
;
return
(
NULL
);
}
return
(
pstrdup
(((
TypeTupleForm
)
GETSTRUCT
(
typeTuple
))
->
typname
.
data
));
}
Oid
SPI_gettypeid
(
TupleDesc
tupdesc
,
int
fnumber
)
{
SPI_error
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_error
=
SPI_ERROR_UNCONNECTED
;
return
(
InvalidOid
);
}
if
(
tupdesc
->
natts
<=
fnumber
||
fnumber
<
0
)
return
(
InvalidOid
);
return
(
tupdesc
->
attrs
[
fnumber
]
->
atttypid
);
}
char
*
SPI_getrelname
(
Relation
rel
)
{
SPI_error
=
0
;
if
(
_SPI_curid
+
1
!=
_SPI_connected
)
{
SPI_error
=
SPI_ERROR_UNCONNECTED
;
return
(
NULL
);
}
return
(
pstrdup
(
rel
->
rd_rel
->
relname
.
data
));
}
static
_SPI_entry
*
_SPI_fnentry
(
int
dspace
,
int
**
tabsz
,
MemoryContext
*
oldcxt
)
static
_SPI_plan
*
_SPI_copy_plan
(
_SPI_plan
*
plan
,
bool
local
)
{
char
*
ident
=
_SPI_current
->
ltab
.
ident
;
int
*
size
=
NULL
;
_SPI_entry
**
ep
=
NULL
;
_SPI_entry
*
entry
;
int
i
;
switch
(
dspace
)
{
case
SPI_DSPACE_SESSION
:
if
(
tabsz
!=
NULL
)
*
oldcxt
=
MemoryContextSwitchTo
(
TopMemoryContext
);
ep
=
&
(
_SPI_stab
);
size
=
&
(
_SPI_stabsz
);
break
;
case
SPI_DSPACE_XACT
:
if
(
tabsz
!=
NULL
)
*
oldcxt
=
MemoryContextSwitchTo
((
MemoryContext
)
PortalGetVariableMemory
(
_SPI_portal
));
ep
=
&
(
_SPI_xtab
);
size
=
&
(
_SPI_xtabsz
);
break
;
}
for
(
i
=
0
;
i
<
*
size
;
i
++
,
ep
++
)
{
if
(
strcmp
((
*
ep
)
->
ident
,
ident
)
==
0
)
break
;
}
if
(
i
==
*
size
)
{
if
(
tabsz
==
NULL
)
/* don't expand table */
return
(
NULL
);
*
tabsz
=
size
;
if
(
*
size
==
0
)
*
ep
=
(
_SPI_entry
*
)
palloc
(
sizeof
(
_SPI_entry
));
else
*
ep
=
(
_SPI_entry
*
)
repalloc
(
*
ep
,
(
*
size
+
1
)
*
sizeof
(
_SPI_entry
));
entry
=
(
*
ep
)
+
*
size
;
entry
->
ident
=
pstrdup
(
ident
);
entry
->
plcnt
=
entry
->
dtcnt
=
0
;
}
else
entry
=
*
ep
;
return
(
entry
);
}
static
int
_SPI_copy_plan
(
int
dspace
,
_SPI_plan
*
plan
)
{
_SPI_entry
*
entry
;
_SPI_plan
*
newplan
;
int
*
tabsz
=
NULL
;
MemoryContext
oldcxt
;
int
i
;
if
(
dspace
==
SPI_DSPACE_LOCAL
)
{
if
(
local
)
oldcxt
=
MemoryContextSwitchTo
((
MemoryContext
)
PortalGetVariableMemory
(
_SPI_current
->
portal
));
entry
=
&
(
_SPI_current
->
ltab
);
}
else
entry
=
_SPI_fnentry
(
dspace
,
&
tabsz
,
&
oldc
xt
);
oldcxt
=
MemoryContextSwitchTo
(
TopMemoryConte
xt
);
if
(
entry
->
plcnt
==
0
)
entry
->
plan
=
(
_SPI_plan
**
)
palloc
(
sizeof
(
_SPI_plan
*
));
else
entry
->
plan
=
(
_SPI_plan
**
)
repalloc
(
entry
->
plan
,
(
entry
->
plcnt
+
1
)
*
sizeof
(
_SPI_plan
*
));
newplan
=
(
_SPI_plan
*
)
palloc
(
sizeof
(
_SPI_plan
));
entry
->
plan
[
entry
->
plcnt
]
=
newplan
;
newplan
->
qtlist
=
(
QueryTreeList
*
)
palloc
(
sizeof
(
QueryTreeList
));
newplan
->
qtlist
->
len
=
plan
->
qtlist
->
len
;
newplan
->
qtlist
->
qtrees
=
(
Query
**
)
palloc
(
plan
->
qtlist
->
len
*
...
...
@@ -856,278 +881,8 @@ _SPI_copy_plan (int dspace, _SPI_plan *plan)
}
else
newplan
->
argtypes
=
NULL
;
(
entry
->
plcnt
)
++
;
if
(
tabsz
!=
NULL
)
/* table expanded */
(
*
tabsz
)
++
;
MemoryContextSwitchTo
(
oldcxt
);
return
(
entry
->
plcnt
-
1
);
}
int
SPI_expdata
(
int
dspace
,
int
count
,
void
**
data
,
int
*
len
)
{
_SPI_entry
*
entry
;
_SPI_data
*
newdata
;
int
*
tabsz
=
NULL
;
MemoryContext
oldcxt
;
int
res
;
int
i
;
if
(
(
dspace
!=
SPI_DSPACE_XACT
&&
dspace
!=
SPI_DSPACE_SESSION
)
||
count
<=
0
||
data
==
NULL
||
len
==
NULL
)
return
(
SPI_ERROR_ARGUMENT
);
res
=
_SPI_begin_call
(
false
);
/* don't change context */
if
(
res
<
0
)
return
(
res
);
entry
=
_SPI_fnentry
(
dspace
,
&
tabsz
,
&
oldcxt
);
if
(
entry
->
dtcnt
==
0
)
entry
->
data
=
(
_SPI_data
*
)
palloc
(
count
*
sizeof
(
_SPI_data
));
else
entry
->
data
=
(
_SPI_data
*
)
repalloc
(
entry
->
data
,
(
entry
->
dtcnt
+
count
)
*
sizeof
(
_SPI_data
));
for
(
i
=
0
,
newdata
=
&
(
entry
->
data
[
entry
->
dtcnt
]);
i
<
count
;
i
++
,
newdata
++
)
{
if
(
len
[
i
]
<=
0
||
data
[
i
]
==
NULL
)
break
;
newdata
->
data
=
(
void
*
)
palloc
(
len
[
i
]);
memcpy
(
newdata
->
data
,
data
[
i
],
len
[
i
]);
newdata
->
len
=
len
[
i
];
}
entry
->
dtcnt
+=
i
;
res
=
i
;
if
(
tabsz
!=
NULL
)
/* table expanded */
(
*
tabsz
)
++
;
MemoryContextSwitchTo
(
oldcxt
);
_SPI_curid
--
;
return
(
res
);
}
int
SPI_impdata
(
int
dspace
,
int
start
,
int
count
,
void
**
data
,
int
**
len
)
{
_SPI_entry
*
entry
;
int
*
dl
;
int
res
;
int
i
;
if
(
(
dspace
!=
SPI_DSPACE_XACT
&&
dspace
!=
SPI_DSPACE_SESSION
)
||
start
<
0
||
count
<
0
||
(
count
>
0
&&
(
data
==
NULL
||
len
==
NULL
)
)
)
return
(
SPI_ERROR_ARGUMENT
);
res
=
_SPI_begin_call
(
false
);
/* don't change context */
if
(
res
<
0
)
return
(
res
);
entry
=
_SPI_fnentry
(
dspace
,
NULL
,
NULL
);
_SPI_curid
--
;
if
(
entry
==
NULL
||
entry
->
dtcnt
==
0
)
return
(
0
);
if
(
count
==
0
)
return
(
entry
->
dtcnt
);
if
(
start
>=
entry
->
dtcnt
)
return
(
0
);
i
=
(
entry
->
dtcnt
-
start
>=
count
)
?
count
:
entry
->
dtcnt
-
start
;
data
=
(
void
**
)
palloc
(
i
*
sizeof
(
void
*
));
dl
=
*
len
=
(
int
*
)
palloc
(
i
*
sizeof
(
int
));
for
(
i
=
start
,
res
=
0
;
i
<
entry
->
dtcnt
&&
res
<
count
;
i
++
,
res
++
)
{
dl
[
res
]
=
entry
->
data
[
i
].
len
;
data
[
res
]
=
(
void
*
)
palloc
(
dl
[
res
]);
memcpy
(
data
[
res
],
entry
->
data
[
i
].
data
,
dl
[
res
]);
}
return
(
res
);
}
int
SPI_expplan
(
int
dspace
,
int
start
,
int
count
)
{
_SPI_entry
*
entry
=
&
(
_SPI_current
->
ltab
);
int
res
;
int
i
;
if
(
(
dspace
!=
SPI_DSPACE_XACT
&&
dspace
!=
SPI_DSPACE_SESSION
)
||
start
<
0
||
count
<=
0
)
return
(
SPI_ERROR_ARGUMENT
);
res
=
_SPI_begin_call
(
false
);
/* don't change context */
if
(
res
<
0
)
return
(
res
);
if
(
start
>=
entry
->
plcnt
)
{
_SPI_curid
--
;
return
(
0
);
}
for
(
i
=
start
,
res
=
0
;
i
<
entry
->
plcnt
&&
res
<
count
;
i
++
,
res
++
)
{
_SPI_copy_plan
(
dspace
,
entry
->
plan
[
i
]);
}
_SPI_curid
--
;
return
(
res
);
}
int
SPI_impplan
(
int
dspace
,
int
start
,
int
count
)
{
_SPI_entry
*
to
=
&
(
_SPI_current
->
ltab
);
_SPI_entry
*
from
;
int
res
;
int
i
;
if
(
(
dspace
!=
SPI_DSPACE_XACT
&&
dspace
!=
SPI_DSPACE_SESSION
)
||
start
<
0
||
count
<
0
)
return
(
SPI_ERROR_ARGUMENT
);
res
=
_SPI_begin_call
(
false
);
/* don't change context */
if
(
res
<
0
)
return
(
res
);
from
=
_SPI_fnentry
(
dspace
,
NULL
,
NULL
);
/* don't expand table */
_SPI_curid
--
;
if
(
from
==
NULL
||
from
->
plcnt
==
0
)
return
(
0
);
if
(
count
==
0
)
return
(
from
->
plcnt
);
if
(
start
>=
from
->
plcnt
)
return
(
0
);
i
=
(
from
->
plcnt
-
start
>=
count
)
?
count
:
from
->
plcnt
-
start
;
if
(
to
->
plcnt
==
0
)
to
->
plan
=
(
_SPI_plan
**
)
palloc
(
i
*
sizeof
(
_SPI_plan
*
));
else
to
->
plan
=
(
_SPI_plan
**
)
repalloc
(
to
->
plan
,
(
to
->
plcnt
+
i
)
*
sizeof
(
_SPI_plan
*
));
for
(
i
=
start
,
res
=
0
;
i
<
from
->
plcnt
&&
res
<
count
;
i
++
,
res
++
)
{
to
->
plan
[
res
]
=
from
->
plan
[
i
];
}
return
(
res
);
}
int
SPI_execp
(
int
pid
,
char
**
Values
,
char
*
Nulls
)
{
_SPI_entry
*
entry
=
&
(
_SPI_current
->
ltab
);
int
res
;
if
(
pid
<
0
)
return
(
SPI_ERROR_ARGUMENT
);
res
=
_SPI_begin_call
(
false
);
if
(
res
<
0
)
return
(
res
);
if
(
entry
->
plcnt
<
pid
)
{
_SPI_curid
--
;
return
(
SPI_ERROR_NOENTRY
);
}
else
if
(
entry
->
plan
[
pid
]
->
nargs
>
0
&&
(
Values
==
NULL
||
Nulls
==
NULL
)
)
{
_SPI_curid
--
;
return
(
SPI_ERROR_PARAM
);
}
_SPI_execmem
();
StartPortalAllocMode
(
DefaultAllocMode
,
0
);
res
=
_SPI_execute_plan
(
entry
->
plan
[
pid
],
Values
,
Nulls
,
0
);
_SPI_end_call
(
true
);
return
(
res
);
}
static
int
_SPI_execute_plan
(
_SPI_plan
*
plan
,
char
**
Values
,
char
*
Nulls
,
int
tcount
)
{
QueryTreeList
*
queryTree_list
=
plan
->
qtlist
;
List
*
planTree_list
=
plan
->
ptlist
;
QueryDesc
*
qdesc
;
Query
*
queryTree
;
Plan
*
planTree
;
EState
*
state
;
int
nargs
=
plan
->
nargs
;
int
qlen
=
queryTree_list
->
len
;
int
res
;
int
i
,
k
;
/* Increment CommandCounter to see changes made by now */
CommandCounterIncrement
();
SPI_processed
=
0
;
SPI_tuptable
=
NULL
;
_SPI_current
->
tuptable
=
NULL
;
_SPI_current
->
qtlist
=
NULL
;
for
(
i
=
0
;
;
i
++
)
{
queryTree
=
(
Query
*
)
(
queryTree_list
->
qtrees
[
i
]);
planTree
=
lfirst
(
planTree_list
);
planTree_list
=
lnext
(
planTree_list
);
if
(
queryTree
->
commandType
==
CMD_UTILITY
)
{
ProcessUtility
(
queryTree
->
utilityStmt
,
None
);
if
(
i
<
qlen
-
1
)
CommandCounterIncrement
();
else
return
(
SPI_OK_UTILITY
);
}
else
{
qdesc
=
CreateQueryDesc
(
queryTree
,
planTree
,
(
i
<
qlen
-
1
)
?
None
:
SPI
);
state
=
CreateExecutorState
();
if
(
nargs
>
0
)
{
ParamListInfo
paramLI
=
(
ParamListInfo
)
palloc
((
nargs
+
1
)
*
sizeof
(
ParamListInfoData
));
state
->
es_param_list_info
=
paramLI
;
for
(
k
=
0
;
k
<
plan
->
nargs
;
paramLI
++
,
k
++
)
{
paramLI
->
kind
=
PARAM_NUM
;
paramLI
->
id
=
i
+
1
;
paramLI
->
isnull
=
(
Nulls
[
i
]
!=
0
);
paramLI
->
value
=
(
Datum
)
Values
[
i
];
}
paramLI
->
kind
=
PARAM_INVALID
;
}
else
state
->
es_param_list_info
=
NULL
;
res
=
_SPI_pquery
(
qdesc
,
state
,
(
i
<
qlen
-
1
)
?
0
:
tcount
);
if
(
res
<
0
||
i
>=
qlen
-
1
)
return
(
res
);
CommandCounterIncrement
();
}
}
return
(
res
);
return
(
newplan
);
}
src/include/executor/spi.h
View file @
bf1d9aeb
...
...
@@ -52,7 +52,6 @@ typedef struct {
#define SPI_ERROR_NOATTRIBUTE -9
#define SPI_ERROR_NOOUTFUNC -10
#define SPI_ERROR_TYPUNKNOWN -11
#define SPI_ERROR_NOENTRY -12
#define SPI_OK_CONNECT 1
#define SPI_OK_FINISH 2
...
...
@@ -65,24 +64,16 @@ typedef struct {
#define SPI_OK_UPDATE 9
#define SPI_OK_CURSOR 10
#define SPI_DSPACE_LOCAL 0
#define SPI_DSPACE_XACT 1
#define SPI_DSPACE_SESSION 2
extern
uint32
SPI_processed
;
extern
SPITupleTable
*
SPI_tuptable
;
extern
int
SPI_
error
;
extern
int
SPI_
result
;
extern
int
SPI_connect
(
char
*
ident
);
extern
int
SPI_connect
(
void
);
extern
int
SPI_finish
(
void
);
extern
int
SPI_exec
(
char
*
src
);
extern
int
SPI_execn
(
char
*
src
,
int
tcount
);
extern
int
SPI_execp
(
int
pid
,
char
**
values
,
char
*
Nulls
);
extern
int
SPI_prepare
(
char
*
src
,
int
nargs
,
Oid
*
argtypes
);
extern
int
SPI_expplan
(
int
dspace
,
int
start
,
int
count
);
extern
int
SPI_impplan
(
int
dspace
,
int
start
,
int
count
);
extern
int
SPI_expdata
(
int
dspace
,
int
count
,
void
**
data
,
int
*
len
);
extern
int
SPI_impdata
(
int
dspace
,
int
start
,
int
count
,
void
**
data
,
int
**
len
);
extern
int
SPI_exec
(
char
*
src
,
int
tcount
);
extern
int
SPI_execp
(
void
*
plan
,
char
**
values
,
char
*
Nulls
,
int
tcount
);
extern
void
*
SPI_prepare
(
char
*
src
,
int
nargs
,
Oid
*
argtypes
);
extern
void
*
SPI_saveplan
(
void
*
plan
);
extern
int
SPI_fnumber
(
TupleDesc
tupdesc
,
char
*
fname
);
extern
char
*
SPI_getvalue
(
HeapTuple
tuple
,
TupleDesc
tupdesc
,
int
fnumber
);
...
...
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