Skip to content
Snippets Groups Projects
Commit 6a9fffcd authored by Tom Lane's avatar Tom Lane
Browse files

Refactor SPI_cursor_open/SPI_cursor_open_with_args so that the latter sets

the PARAM_FLAG_CONST flag on the parameters that are passed into the portal,
while the former's behavior is unchanged.  This should only affect the case
where the portal is executing an EXPLAIN; it will cause the generated plan to
look more like what would be generated if the portal were actually executing
the command being explained.  Per gripe from Pavel.
parent 6d19e9ff
Branches
Tags
No related merge requests found
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.195 2008/05/12 20:02:00 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.196 2008/06/01 17:32:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,6 +36,10 @@ static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */ ...@@ -36,6 +36,10 @@ static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
static int _SPI_connected = -1; static int _SPI_connected = -1;
static int _SPI_curid = -1; static int _SPI_curid = -1;
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
Datum *Values, const char *Nulls,
bool read_only, int pflags);
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan, static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan,
ParamListInfo boundParams); ParamListInfo boundParams);
...@@ -916,6 +920,80 @@ Portal ...@@ -916,6 +920,80 @@ Portal
SPI_cursor_open(const char *name, SPIPlanPtr plan, SPI_cursor_open(const char *name, SPIPlanPtr plan,
Datum *Values, const char *Nulls, Datum *Values, const char *Nulls,
bool read_only) bool read_only)
{
return SPI_cursor_open_internal(name, plan, Values, Nulls,
read_only, 0);
}
/*
* SPI_cursor_open_with_args()
*
* Parse and plan a query and open it as a portal. Like SPI_execute_with_args,
* we can tell the planner to rely on the parameter values as constants,
* because the plan will only be used once.
*/
Portal
SPI_cursor_open_with_args(const char *name,
const char *src,
int nargs, Oid *argtypes,
Datum *Values, const char *Nulls,
bool read_only, int cursorOptions)
{
Portal result;
_SPI_plan plan;
ParamListInfo paramLI;
if (src == NULL || nargs < 0)
elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
if (nargs > 0 && (argtypes == NULL || Values == NULL))
elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
SPI_result = _SPI_begin_call(true);
if (SPI_result < 0)
elog(ERROR, "SPI_cursor_open_with_args called while not connected");
memset(&plan, 0, sizeof(_SPI_plan));
plan.magic = _SPI_PLAN_MAGIC;
plan.cursor_options = cursorOptions;
plan.nargs = nargs;
plan.argtypes = argtypes;
paramLI = _SPI_convert_params(nargs, argtypes,
Values, Nulls,
PARAM_FLAG_CONST);
_SPI_prepare_plan(src, &plan, paramLI);
/* We needn't copy the plan; SPI_cursor_open_internal will do so */
/* Adjust stack so that SPI_cursor_open_internal doesn't complain */
_SPI_curid--;
/* SPI_cursor_open_internal must be called in procedure memory context */
_SPI_procmem();
result = SPI_cursor_open_internal(name, &plan, Values, Nulls,
read_only, PARAM_FLAG_CONST);
/* And clean up */
_SPI_curid++;
_SPI_end_call(true);
return result;
}
/*
* SPI_cursor_open_internal()
*
* Common code for SPI_cursor_open and SPI_cursor_open_with_args
*/
static Portal
SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
Datum *Values, const char *Nulls,
bool read_only, int pflags)
{ {
CachedPlanSource *plansource; CachedPlanSource *plansource;
CachedPlan *cplan; CachedPlan *cplan;
...@@ -997,7 +1075,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan, ...@@ -997,7 +1075,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
ParamExternData *prm = &paramLI->params[k]; ParamExternData *prm = &paramLI->params[k];
prm->ptype = plan->argtypes[k]; prm->ptype = plan->argtypes[k];
prm->pflags = 0; prm->pflags = pflags;
prm->isnull = (Nulls && Nulls[k] == 'n'); prm->isnull = (Nulls && Nulls[k] == 'n');
if (prm->isnull) if (prm->isnull)
{ {
...@@ -1129,64 +1207,6 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan, ...@@ -1129,64 +1207,6 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
} }
/*
* SPI_cursor_open_with_args()
*
* Parse and plan a query and open it as a portal. Like SPI_execute_with_args,
* we can tell the planner to rely on the parameter values as constants,
* because the plan will only be used once.
*/
Portal
SPI_cursor_open_with_args(const char *name,
const char *src,
int nargs, Oid *argtypes,
Datum *Values, const char *Nulls,
bool read_only, int cursorOptions)
{
Portal result;
_SPI_plan plan;
ParamListInfo paramLI;
if (src == NULL || nargs < 0)
elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
if (nargs > 0 && (argtypes == NULL || Values == NULL))
elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
SPI_result = _SPI_begin_call(true);
if (SPI_result < 0)
elog(ERROR, "SPI_cursor_open_with_args called while not connected");
memset(&plan, 0, sizeof(_SPI_plan));
plan.magic = _SPI_PLAN_MAGIC;
plan.cursor_options = cursorOptions;
plan.nargs = nargs;
plan.argtypes = argtypes;
paramLI = _SPI_convert_params(nargs, argtypes,
Values, Nulls,
PARAM_FLAG_CONST);
_SPI_prepare_plan(src, &plan, paramLI);
/* We needn't copy the plan; SPI_cursor_open will do so */
/* Adjust stack so that SPI_cursor_open doesn't complain */
_SPI_curid--;
/* SPI_cursor_open expects to be called in procedure memory context */
_SPI_procmem();
result = SPI_cursor_open(name, &plan, Values, Nulls, read_only);
/* And clean up */
_SPI_curid++;
_SPI_end_call(true);
return result;
}
/* /*
* SPI_cursor_find() * SPI_cursor_find()
* *
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment