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.
This commit is contained in:
Tom Lane 2008-06-01 17:32:48 +00:00
parent 6d19e9ffad
commit 6a9fffcd0d
1 changed files with 80 additions and 60 deletions

View File

@ -8,7 +8,7 @@
*
*
* 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 */
static int _SPI_connected = -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,
ParamListInfo boundParams);
@ -916,6 +920,80 @@ Portal
SPI_cursor_open(const char *name, SPIPlanPtr plan,
Datum *Values, const char *Nulls,
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;
CachedPlan *cplan;
@ -997,7 +1075,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
ParamExternData *prm = &paramLI->params[k];
prm->ptype = plan->argtypes[k];
prm->pflags = 0;
prm->pflags = pflags;
prm->isnull = (Nulls && Nulls[k] == 'n');
if (prm->isnull)
{
@ -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()
*