summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2008-06-01 17:32:48 +0000
committerTom Lane2008-06-01 17:32:48 +0000
commitcfef6adeecc9003f3120c106fa83f40619c15d12 (patch)
treefb71aa1dd8650c75096e062e29e8425d9de5f758
parent0256045826907a6c38e5a9682d01ada168238890 (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.c138
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 = &paramLI->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