diff options
author | Tom Lane | 2008-06-01 17:32:48 +0000 |
---|---|---|
committer | Tom Lane | 2008-06-01 17:32:48 +0000 |
commit | cfef6adeecc9003f3120c106fa83f40619c15d12 (patch) | |
tree | fb71aa1dd8650c75096e062e29e8425d9de5f758 | |
parent | 0256045826907a6c38e5a9682d01ada168238890 (diff) |
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.
-rw-r--r-- | src/backend/executor/spi.c | 138 |
1 files changed, 79 insertions, 59 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index c3789e4e03..6770138143 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -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); @@ -917,6 +921,80 @@ 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; List *stmt_list; @@ -997,7 +1075,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan, ParamExternData *prm = ¶mLI->params[k]; prm->ptype = plan->argtypes[k]; - prm->pflags = 0; + prm->pflags = pflags; prm->isnull = (Nulls && Nulls[k] == 'n'); if (prm->isnull) { @@ -1130,64 +1208,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() * * Find the portal of an existing open cursor |