Refactor SPI_cursor_open/SPI_cursor_open_with_args so that the latter sets
authorTom Lane
Sun, 1 Jun 2008 17:32:48 +0000 (17:32 +0000)
committerTom Lane
Sun, 1 Jun 2008 17:32:48 +0000 (17:32 +0000)
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.

src/backend/executor/spi.c

index 555bdd1a6f265094d432c33aa5d52061ce59724d..32e53265d975c6320219120a3e9955ae79db4c5a 100644 (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 = ¶mLI->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()
  *