Simplify ParamListInfo data structure to support only numbered parameters,
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 22 Apr 2006 01:26:01 +0000 (01:26 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 22 Apr 2006 01:26:01 +0000 (01:26 +0000)
not named ones, and replace linear searches of the list with array indexing.
The named-parameter support has been dead code for many years anyway,
and recent profiling suggests that the searching was costing a noticeable
amount of performance for complex queries.

20 files changed:
src/backend/commands/prepare.c
src/backend/executor/execQual.c
src/backend/executor/functions.c
src/backend/executor/spi.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/params.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/util/clauses.c
src/backend/parser/analyze.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/tcop/postgres.c
src/backend/utils/adt/ruleutils.c
src/include/catalog/catversion.h
src/include/nodes/params.h
src/include/nodes/primnodes.h
src/pl/plpgsql/src/pl_exec.c

index c0fbbabdbaa1dd67834d6166c275ac787c080816..0892ab9fbb030e2cee16ffbd943a6dec0282995e 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2006, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.49 2006/03/05 15:58:24 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.50 2006/04/22 01:25:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -247,30 +247,30 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
        if (list_length(params) != nargs)
                elog(ERROR, "wrong number of arguments");
 
+       if (nargs == 0)
+               return NULL;
+
        exprstates = (List *) ExecPrepareExpr((Expr *) params, estate);
 
-       paramLI = (ParamListInfo)
-               palloc0((nargs + 1) * sizeof(ParamListInfoData));
+       /* sizeof(ParamListInfoData) includes the first array element */
+       paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
+                                                                        (nargs - 1) * sizeof(ParamExternData));
+       paramLI->numParams = nargs;
 
        forboth(le, exprstates, la, argtypes)
        {
                ExprState  *n = lfirst(le);
-               bool            isNull;
+               ParamExternData *prm = &paramLI->params[i];
 
-               paramLI[i].value = ExecEvalExprSwitchContext(n,
-                                                                                         GetPerTupleExprContext(estate),
-                                                                                                        &isNull,
-                                                                                                        NULL);
-               paramLI[i].kind = PARAM_NUM;
-               paramLI[i].id = i + 1;
-               paramLI[i].ptype = lfirst_oid(la);
-               paramLI[i].isnull = isNull;
+               prm->ptype = lfirst_oid(la);
+               prm->value = ExecEvalExprSwitchContext(n,
+                                                                                          GetPerTupleExprContext(estate),
+                                                                                          &prm->isnull,
+                                                                                          NULL);
 
                i++;
        }
 
-       paramLI[i].kind = PARAM_INVALID;
-
        return paramLI;
 }
 
index fcc7d4b683c37fc4b9943b242d524ff66bd0e62b..41ea452df5859c19a99fc29abc3291fba730ccd7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.189 2006/03/10 01:51:23 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.190 2006/04/22 01:25:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -605,13 +605,12 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
                          bool *isNull, ExprDoneCond *isDone)
 {
        Param      *expression = (Param *) exprstate->expr;
-       int                     thisParamKind = expression->paramkind;
-       AttrNumber      thisParamId = expression->paramid;
+       int                     thisParamId = expression->paramid;
 
        if (isDone)
                *isDone = ExprSingleResult;
 
-       if (thisParamKind == PARAM_EXEC)
+       if (expression->paramkind == PARAM_EXEC)
        {
                /*
                 * PARAM_EXEC params (internal executor parameters) are stored in the
@@ -633,18 +632,27 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
        else
        {
                /*
-                * All other parameter types must be sought in ecxt_param_list_info.
+                * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
                 */
-               ParamListInfo paramInfo;
-
-               paramInfo = lookupParam(econtext->ecxt_param_list_info,
-                                                               thisParamKind,
-                                                               expression->paramname,
-                                                               thisParamId,
-                                                               false);
-               Assert(paramInfo->ptype == expression->paramtype);
-               *isNull = paramInfo->isnull;
-               return paramInfo->value;
+               ParamListInfo paramInfo = econtext->ecxt_param_list_info;
+
+               Assert(expression->paramkind == PARAM_EXTERN);
+               if (paramInfo &&
+                       thisParamId > 0 && thisParamId <= paramInfo->numParams)
+               {
+                       ParamExternData *prm = &paramInfo->params[thisParamId - 1];
+
+                       if (OidIsValid(prm->ptype))
+                       {
+                               Assert(prm->ptype == expression->paramtype);
+                               *isNull = prm->isnull;
+                               return prm->value;
+                       }
+               }
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("no value found for parameter %d", thisParamId)));
+               return (Datum) 0;               /* keep compiler quiet */
        }
 }
 
index 0fc4d7b59b2f268f98d5395321e71a507f26f450..92e43c1dc57192cbb25a729d2f09fd9871775d86 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.101 2006/03/05 15:58:26 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.102 2006/04/22 01:25:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -431,17 +431,19 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
        {
                int                     i;
 
-               paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
+               /* sizeof(ParamListInfoData) includes the first array element */
+               paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
+                                                                        (nargs - 1) * sizeof(ParamExternData));
+               paramLI->numParams = nargs;
 
                for (i = 0; i < nargs; i++)
                {
-                       paramLI[i].kind = PARAM_NUM;
-                       paramLI[i].id = i + 1;
-                       paramLI[i].ptype = fcache->argtypes[i];
-                       paramLI[i].value = fcinfo->arg[i];
-                       paramLI[i].isnull = fcinfo->argnull[i];
+                       ParamExternData *prm = &paramLI->params[i];
+
+                       prm->value = fcinfo->arg[i];
+                       prm->isnull = fcinfo->argnull[i];
+                       prm->ptype = fcache->argtypes[i];
                }
-               paramLI[nargs].kind = PARAM_INVALID;
        }
        else
                paramLI = NULL;
index 3563ba23d3ad2f7cbb8f2fed207402b3714936b9..333968676d4f8c40fd5fe8ae6de1e5689ed5d66a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.150 2006/04/04 19:35:34 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.151 2006/04/22 01:25:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -885,19 +885,21 @@ SPI_cursor_open(const char *name, void *plan,
        /* If the plan has parameters, set them up */
        if (spiplan->nargs > 0)
        {
-               paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) *
-                                                                                 sizeof(ParamListInfoData));
+               /* sizeof(ParamListInfoData) includes the first array element */
+               paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
+                                                       (spiplan->nargs - 1) * sizeof(ParamExternData));
+               paramLI->numParams = spiplan->nargs;
 
                for (k = 0; k < spiplan->nargs; k++)
                {
-                       paramLI[k].kind = PARAM_NUM;
-                       paramLI[k].id = k + 1;
-                       paramLI[k].ptype = spiplan->argtypes[k];
-                       paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
-                       if (paramLI[k].isnull)
+                       ParamExternData *prm = &paramLI->params[k];
+
+                       prm->ptype = spiplan->argtypes[k];
+                       prm->isnull = (Nulls && Nulls[k] == 'n');
+                       if (prm->isnull)
                        {
                                /* nulls just copy */
-                               paramLI[k].value = Values[k];
+                               prm->value = Values[k];
                        }
                        else
                        {
@@ -905,13 +907,11 @@ SPI_cursor_open(const char *name, void *plan,
                                int16           paramTypLen;
                                bool            paramTypByVal;
 
-                               get_typlenbyval(spiplan->argtypes[k],
-                                                               &paramTypLen, &paramTypByVal);
-                               paramLI[k].value = datumCopy(Values[k],
-                                                                                        paramTypByVal, paramTypLen);
+                               get_typlenbyval(prm->ptype, &paramTypLen, &paramTypByVal);
+                               prm->value = datumCopy(Values[k],
+                                                                          paramTypByVal, paramTypLen);
                        }
                }
-               paramLI[k].kind = PARAM_INVALID;
        }
        else
                paramLI = NULL;
@@ -1334,18 +1334,19 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
                {
                        int                     k;
 
-                       paramLI = (ParamListInfo)
-                               palloc0((nargs + 1) * sizeof(ParamListInfoData));
+                       /* sizeof(ParamListInfoData) includes the first array element */
+                       paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
+                                                                        (nargs - 1) * sizeof(ParamExternData));
+                       paramLI->numParams = nargs;
 
                        for (k = 0; k < nargs; k++)
                        {
-                               paramLI[k].kind = PARAM_NUM;
-                               paramLI[k].id = k + 1;
-                               paramLI[k].ptype = plan->argtypes[k];
-                               paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
-                               paramLI[k].value = Values[k];
+                               ParamExternData *prm = &paramLI->params[k];
+
+                               prm->value = Values[k];
+                               prm->isnull = (Nulls && Nulls[k] == 'n');
+                               prm->ptype = plan->argtypes[k];
                        }
-                       paramLI[k].kind = PARAM_INVALID;
                }
                else
                        paramLI = NULL;
index cd8ebe1f5d68b1780217349026fdd34c77f0c7f1..b060d38b5edb0ccb0e1f48c77d2c48bac109ece7 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.333 2006/04/15 17:45:34 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.334 2006/04/22 01:25:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -729,7 +729,6 @@ _copyParam(Param *from)
 
        COPY_SCALAR_FIELD(paramkind);
        COPY_SCALAR_FIELD(paramid);
-       COPY_STRING_FIELD(paramname);
        COPY_SCALAR_FIELD(paramtype);
 
        return newnode;
index 9aa0b399b7c12c39ddfb35f6ab9cff4539bf71b0..94799d0c85f50a2b0129f70b60250911e27a8c41 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.269 2006/04/15 17:45:34 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.270 2006/04/22 01:25:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -147,23 +147,9 @@ static bool
 _equalParam(Param *a, Param *b)
 {
        COMPARE_SCALAR_FIELD(paramkind);
+       COMPARE_SCALAR_FIELD(paramid);
        COMPARE_SCALAR_FIELD(paramtype);
 
-       switch (a->paramkind)
-       {
-               case PARAM_NAMED:
-                       COMPARE_STRING_FIELD(paramname);
-                       break;
-               case PARAM_NUM:
-               case PARAM_EXEC:
-               case PARAM_SUBLINK:
-                       COMPARE_SCALAR_FIELD(paramid);
-                       break;
-               default:
-                       elog(ERROR, "unrecognized paramkind: %d",
-                                a->paramkind);
-       }
-
        return true;
 }
 
index 58e800bab2b19fccdd1e3e4cf570f12f18b2308a..314d68d2ef9076a614fa1556d77723412ce8bae4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.272 2006/03/23 00:19:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.273 2006/04/22 01:25:59 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -624,9 +624,8 @@ _outParam(StringInfo str, Param *node)
 {
        WRITE_NODE_TYPE("PARAM");
 
-       WRITE_INT_FIELD(paramkind);
+       WRITE_ENUM_FIELD(paramkind, ParamKind);
        WRITE_INT_FIELD(paramid);
-       WRITE_STRING_FIELD(paramname);
        WRITE_OID_FIELD(paramtype);
 }
 
index 618a1c1e816f4731c383cf00be6350d6e6aacd63..1d4e1d48e8b45a6dd38afb51567cca748b6da97e 100644 (file)
@@ -1,13 +1,14 @@
 /*-------------------------------------------------------------------------
  *
  * params.c
- *       Support functions for plan parameter lists.
+ *       Support for finding the values associated with Param nodes.
+ *
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/params.c,v 1.5 2006/03/05 15:58:28 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/params.c,v 1.6 2006/04/22 01:25:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +21,7 @@
 
 
 /*
- * Copy a ParamList.
+ * Copy a ParamListInfo structure.
  *
  * The result is allocated in CurrentMemoryContext.
  */
@@ -28,97 +29,34 @@ ParamListInfo
 copyParamList(ParamListInfo from)
 {
        ParamListInfo retval;
-       int                     i,
-                               size;
+       Size            size;
+       int                     i;
 
-       if (from == NULL)
+       if (from == NULL || from->numParams <= 0)
                return NULL;
 
-       size = 0;
-       while (from[size].kind != PARAM_INVALID)
-               size++;
+       /* sizeof(ParamListInfoData) includes the first array element */
+       size = sizeof(ParamListInfoData) +
+               (from->numParams - 1) * sizeof(ParamExternData);
 
-       retval = (ParamListInfo) palloc0((size + 1) * sizeof(ParamListInfoData));
+       retval = (ParamListInfo) palloc(size);
+       memcpy(retval, from, size);
 
-       for (i = 0; i < size; i++)
+       /*
+        * Flat-copy is not good enough for pass-by-ref data values, so make
+        * a pass over the array to copy those.
+        */
+       for (i = 0; i < retval->numParams; i++)
        {
-               /* copy metadata */
-               retval[i].kind = from[i].kind;
-               if (from[i].kind == PARAM_NAMED)
-                       retval[i].name = pstrdup(from[i].name);
-               retval[i].id = from[i].id;
-               retval[i].ptype = from[i].ptype;
-
-               /* copy value */
-               retval[i].isnull = from[i].isnull;
-               if (from[i].isnull)
-               {
-                       retval[i].value = from[i].value;        /* nulls just copy */
-               }
-               else
-               {
-                       int16           typLen;
-                       bool            typByVal;
-
-                       get_typlenbyval(from[i].ptype, &typLen, &typByVal);
-                       retval[i].value = datumCopy(from[i].value, typByVal, typLen);
-               }
+               ParamExternData *prm = &retval->params[i];
+               int16           typLen;
+               bool            typByVal;
+
+               if (prm->isnull || !OidIsValid(prm->ptype))
+                       continue;
+               get_typlenbyval(prm->ptype, &typLen, &typByVal);
+               prm->value = datumCopy(prm->value, typByVal, typLen);
        }
 
-       retval[size].kind = PARAM_INVALID;
-
        return retval;
 }
-
-/*
- * Search a ParamList for a given parameter.
- *
- * On success, returns a pointer to the parameter's entry.
- * On failure, returns NULL if noError is true, else ereports the error.
- */
-ParamListInfo
-lookupParam(ParamListInfo paramList, int thisParamKind,
-                       const char *thisParamName, AttrNumber thisParamId,
-                       bool noError)
-{
-       if (paramList != NULL)
-       {
-               while (paramList->kind != PARAM_INVALID)
-               {
-                       if (thisParamKind == paramList->kind)
-                       {
-                               switch (thisParamKind)
-                               {
-                                       case PARAM_NAMED:
-                                               if (strcmp(paramList->name, thisParamName) == 0)
-                                                       return paramList;
-                                               break;
-                                       case PARAM_NUM:
-                                               if (paramList->id == thisParamId)
-                                                       return paramList;
-                                               break;
-                                       default:
-                                               elog(ERROR, "unrecognized paramkind: %d",
-                                                        thisParamKind);
-                               }
-                       }
-                       paramList++;
-               }
-       }
-
-       if (!noError)
-       {
-               if (thisParamKind == PARAM_NAMED)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                        errmsg("no value found for parameter \"%s\"",
-                                                       thisParamName)));
-               else
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                        errmsg("no value found for parameter %d",
-                                                       thisParamId)));
-       }
-
-       return NULL;
-}
index 4e762d3a2ecbcff27208ccc75d3dd44e9a6b54ac..9fdf02fd5682c13e3276cd5357d822414b8a1f8d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.187 2006/03/16 00:31:55 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.188 2006/04/22 01:25:59 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -318,9 +318,8 @@ _readParam(void)
 {
        READ_LOCALS(Param);
 
-       READ_INT_FIELD(paramkind);
+       READ_ENUM_FIELD(paramkind, ParamKind);
        READ_INT_FIELD(paramid);
-       READ_STRING_FIELD(paramname);
        READ_OID_FIELD(paramtype);
 
        READ_DONE();
index 1b64bf1c93130c58eba2e91655b43ea52e49a7fa..5296bb04359670e97f53a010884f8ed6839dd49d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.104 2006/03/05 15:58:30 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.105 2006/04/22 01:25:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -163,7 +163,7 @@ replace_outer_var(Var *var)
 
        retval = makeNode(Param);
        retval->paramkind = PARAM_EXEC;
-       retval->paramid = (AttrNumber) i;
+       retval->paramid = i;
        retval->paramtype = var->vartype;
 
        return retval;
@@ -201,7 +201,7 @@ replace_outer_agg(Aggref *agg)
 
        retval = makeNode(Param);
        retval->paramkind = PARAM_EXEC;
-       retval->paramid = (AttrNumber) i;
+       retval->paramid = i;
        retval->paramtype = agg->aggtype;
 
        return retval;
@@ -222,7 +222,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
 
        retval = makeNode(Param);
        retval->paramkind = PARAM_EXEC;
-       retval->paramid = (AttrNumber) list_length(PlannerParamList);
+       retval->paramid = list_length(PlannerParamList);
        retval->paramtype = paramtype;
 
        pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
@@ -1211,7 +1211,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
        {
                if (((Param *) node)->paramkind == PARAM_EXEC)
                {
-                       int                     paramid = (int) ((Param *) node)->paramid;
+                       int                     paramid = ((Param *) node)->paramid;
 
                        context->paramids = bms_add_member(context->paramids, paramid);
                }
index aa21dfdac95406318b4829010c7a028997cf65d5..10a994bcb3fd1bef9daa64211c2c9d2bb1e08d61 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.210 2006/03/14 22:48:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.211 2006/04/22 01:25:59 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -1500,36 +1500,35 @@ eval_const_expressions_mutator(Node *node,
                Param      *param = (Param *) node;
 
                /* OK to try to substitute value? */
-               if (context->estimate && param->paramkind != PARAM_EXEC &&
+               if (context->estimate && param->paramkind == PARAM_EXTERN &&
                        PlannerBoundParamList != NULL)
                {
-                       ParamListInfo paramInfo;
-
-                       /* Search to see if we've been given a value for this Param */
-                       paramInfo = lookupParam(PlannerBoundParamList,
-                                                                       param->paramkind,
-                                                                       param->paramname,
-                                                                       param->paramid,
-                                                                       true);
-                       if (paramInfo)
+                       /* Look to see if we've been given a value for this Param */
+                       if (param->paramid > 0 &&
+                               param->paramid <= PlannerBoundParamList->numParams)
                        {
-                               /*
-                                * Found it, so return a Const representing the param value.
-                                * Note that we don't copy pass-by-ref datatypes, so the Const
-                                * will only be valid as long as the bound parameter list
-                                * exists. This is okay for intended uses of
-                                * estimate_expression_value().
-                                */
-                               int16           typLen;
-                               bool            typByVal;
-
-                               Assert(paramInfo->ptype == param->paramtype);
-                               get_typlenbyval(param->paramtype, &typLen, &typByVal);
-                               return (Node *) makeConst(param->paramtype,
-                                                                                 (int) typLen,
-                                                                                 paramInfo->value,
-                                                                                 paramInfo->isnull,
-                                                                                 typByVal);
+                               ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
+
+                               if (OidIsValid(prm->ptype))
+                               {
+                                       /*
+                                        * Found it, so return a Const representing the param
+                                        * value.  Note that we don't copy pass-by-ref datatypes,
+                                        * so the Const will only be valid as long as the bound
+                                        * parameter list exists.  This is okay for intended uses
+                                        * of estimate_expression_value().
+                                        */
+                                       int16           typLen;
+                                       bool            typByVal;
+
+                                       Assert(prm->ptype == param->paramtype);
+                                       get_typlenbyval(param->paramtype, &typLen, &typByVal);
+                                       return (Node *) makeConst(param->paramtype,
+                                                                                         (int) typLen,
+                                                                                         prm->value,
+                                                                                         prm->isnull,
+                                                                                         typByVal);
+                               }
                        }
                }
                /* Not replaceable, so just copy the Param (no need to recurse) */
@@ -2810,8 +2809,8 @@ substitute_actual_parameters_mutator(Node *node,
        {
                Param      *param = (Param *) node;
 
-               if (param->paramkind != PARAM_NUM)
-                       elog(ERROR, "unexpected paramkind: %d", param->paramkind);
+               if (param->paramkind != PARAM_EXTERN)
+                       elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
                if (param->paramid <= 0 || param->paramid > context->nargs)
                        elog(ERROR, "invalid paramid: %d", param->paramid);
 
index 39c562b8188f9d6d09e7f9a1eccdc38fc11b591c..d69c0f17864c62a582f89296f9b2f3d1eccdabee 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.332 2006/03/23 00:19:29 tgl Exp $
+ *     $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.333 2006/04/22 01:25:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3205,7 +3205,7 @@ check_parameter_resolution_walker(Node *node,
        {
                Param      *param = (Param *) node;
 
-               if (param->paramkind == PARAM_NUM)
+               if (param->paramkind == PARAM_EXTERN)
                {
                        int                     paramno = param->paramid;
 
index 98393a54aa11d64564bbc0822a214c35d8e470a2..3f5d8563f60d0e88692cb0df160d42ba27e415af 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.137 2006/04/05 22:11:55 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.138 2006/04/22 01:25:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -210,7 +210,7 @@ coerce_type(ParseState *pstate, Node *node,
                return result;
        }
        if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
-               ((Param *) node)->paramkind == PARAM_NUM &&
+               ((Param *) node)->paramkind == PARAM_EXTERN &&
                pstate != NULL && pstate->p_variableparams)
        {
                /*
index cae682c9e775ea271255a1205ff8052fa902df14..414afe6dfa536abcf92a97bbb1991a8b11f8da2a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.191 2006/03/14 22:48:21 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.192 2006/04/22 01:26:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -568,8 +568,8 @@ transformParamRef(ParseState *pstate, ParamRef *pref)
        }
 
        param = makeNode(Param);
-       param->paramkind = PARAM_NUM;
-       param->paramid = (AttrNumber) paramno;
+       param->paramkind = PARAM_EXTERN;
+       param->paramid = paramno;
        param->paramtype = toppstate->p_paramtypes[paramno - 1];
 
        return (Node *) param;
@@ -1177,7 +1177,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
 
                        param = makeNode(Param);
                        param->paramkind = PARAM_SUBLINK;
-                       param->paramid = (AttrNumber) tent->resno;
+                       param->paramid = tent->resno;
                        param->paramtype = exprType((Node *) tent->expr);
 
                        right_list = lappend(right_list, param);
index 3c24fa532a6bd089e69ce8b1170c7d62b2f9feea..04e432594e352af984a3162ab13769428d0acb31 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.484 2006/04/18 00:52:23 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.485 2006/04/22 01:26:00 tgl Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -1479,8 +1479,10 @@ exec_bind_message(StringInfo input_message)
 
                oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
 
-               params = (ParamListInfo)
-                       palloc0((numParams + 1) * sizeof(ParamListInfoData));
+               /* sizeof(ParamListInfoData) includes the first array element */
+               params = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
+                                                               (numParams - 1) * sizeof(ParamExternData));
+               params->numParams = numParams;
 
                i = 0;
                foreach(l, pstmt->argtype_list)
@@ -1545,8 +1547,10 @@ exec_bind_message(StringInfo input_message)
                                else
                                        pstring = pg_client_to_server(pbuf.data, plength);
 
-                               params[i].value = OidInputFunctionCall(typinput, pstring,
-                                                                                                          typioparam, -1);
+                               params->params[i].value = OidInputFunctionCall(typinput,
+                                                                                                                          pstring,
+                                                                                                                          typioparam,
+                                                                                                                          -1);
                                /* Free result of encoding conversion, if any */
                                if (pstring && pstring != pbuf.data)
                                        pfree(pstring);
@@ -1567,8 +1571,10 @@ exec_bind_message(StringInfo input_message)
                                else
                                        bufptr = &pbuf;
 
-                               params[i].value = OidReceiveFunctionCall(typreceive, bufptr,
-                                                                                                                typioparam, -1);
+                               params->params[i].value = OidReceiveFunctionCall(typreceive,
+                                                                                                                                bufptr,
+                                                                                                                                typioparam,
+                                                                                                                                -1);
 
                                /* Trouble if it didn't eat the whole buffer */
                                if (!isNull && pbuf.cursor != pbuf.len)
@@ -1589,16 +1595,12 @@ exec_bind_message(StringInfo input_message)
                        if (!isNull)
                                pbuf.data[plength] = csave;
 
-                       params[i].kind = PARAM_NUM;
-                       params[i].id = i + 1;
-                       params[i].ptype = ptype;
-                       params[i].isnull = isNull;
+                       params->params[i].isnull = isNull;
+                       params->params[i].ptype = ptype;
 
                        i++;
                }
 
-               params[i].kind = PARAM_INVALID;
-
                MemoryContextSwitchTo(oldContext);
        }
        else
index 902af40d9fcf199883bec772c8eff589cb60bbad..c0db64bf8960d45c40eb12d6a789f9a351967038 100644 (file)
@@ -2,7 +2,7 @@
  * ruleutils.c - Functions to convert stored expressions/querytrees
  *                             back to source text
  *
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.219 2006/04/08 18:49:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.220 2006/04/22 01:26:00 tgl Exp $
  **********************************************************************/
 
 #include "postgres.h"
@@ -3120,24 +3120,7 @@ get_rule_expr(Node *node, deparse_context *context,
                        break;
 
                case T_Param:
-                       {
-                               Param      *param = (Param *) node;
-
-                               switch (param->paramkind)
-                               {
-                                       case PARAM_NAMED:
-                                               appendStringInfo(buf, "$%s", param->paramname);
-                                               break;
-                                       case PARAM_NUM:
-                                       case PARAM_EXEC:
-                                       case PARAM_SUBLINK:
-                                               appendStringInfo(buf, "$%d", param->paramid);
-                                               break;
-                                       default:
-                                               appendStringInfo(buf, "(param)");
-                                               break;
-                               }
-                       }
+                       appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
                        break;
 
                case T_Aggref:
index 6b59dd55fe1d3753d816625b486a9919d4106cd2..a88d3cfd5971d4427a13376381cbc95ad3098db9 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.322 2006/04/05 22:11:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.323 2006/04/22 01:26:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200604051
+#define CATALOG_VERSION_NO     200604211
 
 #endif
index a00ded8e0a6a8688e6a1410519f451bda6cd57df..13eb25876dd56746be742a22391b793f85a09302 100644 (file)
@@ -1,87 +1,47 @@
 /*-------------------------------------------------------------------------
  *
  * params.h
- *       Declarations of stuff needed to handle parameterized plans.
+ *       Support for finding the values associated with Param nodes.
  *
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.30 2006/03/05 15:58:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.31 2006/04/22 01:26:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef PARAMS_H
 #define PARAMS_H
 
-#include "access/attnum.h"
-
-
-/* ----------------
- * The following are the possible values for the 'paramkind'
- * field of a Param node.
- *
- * PARAM_NAMED: The parameter has a name, i.e. something
- *                             like `$.salary' or `$.foobar'.
- *                             In this case field `paramname' must be a valid name.
- *
- * PARAM_NUM:  The parameter has only a numeric identifier,
- *                             i.e. something like `$1', `$2' etc.
- *                             The number is contained in the `paramid' field.
- *
- * PARAM_EXEC: The parameter is an internal executor parameter.
- *                             It has a number contained in the `paramid' field.
- *
- * PARAM_SUBLINK: The parameter represents an output column of a SubLink
- *                             node's sub-select.  The column number is contained in the
- *                             `paramid' field.  (This type of Param is converted to
- *                             PARAM_EXEC during planning.)
- *
- * PARAM_INVALID should never appear in a Param node; it's used to mark
- * the end of a ParamListInfo array.
- *
- * NOTE: As of PostgreSQL 7.3, named parameters aren't actually used and
- * so the code that handles PARAM_NAMED cases is dead code.  We leave it
- * in place since it might be resurrected someday.
- * ----------------
- */
-
-#define PARAM_NAMED            11
-#define PARAM_NUM              12
-#define PARAM_EXEC             15
-#define PARAM_SUBLINK  16
-#define PARAM_INVALID  100
-
 
 /* ----------------
  *       ParamListInfo
  *
- *       ParamListInfo entries are used to pass parameters into the executor
+ *       ParamListInfo arrays are used to pass parameters into the executor
  *       for parameterized plans.      Each entry in the array defines the value
- *       to be substituted for a PARAM_NAMED or PARAM_NUM parameter.
+ *       to be substituted for a PARAM_EXTERN parameter.  The "paramid"
+ *       of a PARAM_EXTERN Param can range from 1 to numParams.
  *
- *             kind   : the kind of parameter (PARAM_NAMED or PARAM_NUM)
- *             name   : the parameter name (valid if kind == PARAM_NAMED)
- *             id         : the parameter id (valid if kind == PARAM_NUM)
- *             ptype  : the type of the parameter value
- *             isnull : true if the value is null (if so 'value' is undefined)
- *             value  : the value that has to be substituted in the place
- *                              of the parameter.
+ *       Although parameter numbers are normally consecutive, we allow
+ *       ptype == InvalidOid to signal an unused array entry.
  *
- *      ParamListInfo is to be used as an array of ParamListInfoData
- *      records.  A dummy record with kind == PARAM_INVALID marks the end
- *      of the array.
+ *       Although the data structure is really an array, not a list, we keep
+ *       the old typedef name to avoid unnecessary code changes.
  * ----------------
  */
 
+typedef struct ParamExternData
+{
+       Datum           value;                  /* parameter value */
+       bool            isnull;                 /* is it NULL? */
+       Oid                     ptype;                  /* parameter's datatype, or 0 */
+} ParamExternData;
+
 typedef struct ParamListInfoData
 {
-       int                     kind;
-       char       *name;
-       AttrNumber      id;
-       Oid                     ptype;
-       bool            isnull;
-       Datum           value;
+       int                     numParams;              /* number of ParamExternDatas following */
+       ParamExternData params[1];      /* VARIABLE LENGTH ARRAY */
 } ParamListInfoData;
 
 typedef ParamListInfoData *ParamListInfo;
@@ -114,8 +74,5 @@ typedef struct ParamExecData
 
 /* Functions found in src/backend/nodes/params.c */
 extern ParamListInfo copyParamList(ParamListInfo from);
-extern ParamListInfo lookupParam(ParamListInfo paramList, int thisParamKind,
-                       const char *thisParamName, AttrNumber thisParamId,
-                       bool noError);
 
 #endif   /* PARAMS_H */
index 65d5d8ff0c7e59f066219d9e50c58dd651c7c056..9c1f580fc981b65dbb9ab0c414750ea708a8ab87 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.112 2006/03/05 15:58:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.113 2006/04/22 01:26:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -146,18 +146,15 @@ typedef struct Const
 /* ----------------
  * Param
  *             paramkind - specifies the kind of parameter. The possible values
- *             for this field are specified in "params.h", and they are:
+ *             for this field are:
  *
- *             PARAM_NAMED: The parameter has a name, i.e. something
- *                             like `$.salary' or `$.foobar'.
- *                             In this case field `paramname' must be a valid name.
+ *             PARAM_EXTERN:  The parameter value is supplied from outside the plan.
+ *                             Such parameters are numbered from 1 to n.
  *
- *             PARAM_NUM:       The parameter has only a numeric identifier,
- *                             i.e. something like `$1', `$2' etc.
- *                             The number is contained in the `paramid' field.
- *
- *             PARAM_EXEC:  The parameter is an internal executor parameter.
- *                             It has a number contained in the `paramid' field.
+ *             PARAM_EXEC:  The parameter is an internal executor parameter, used
+ *                             for passing values into and out of sub-queries.
+ *                             For historical reasons, such parameters are numbered from 0.
+ *                             These numbers are independent of PARAM_EXTERN numbers.
  *
  *             PARAM_SUBLINK:  The parameter represents an output column of a SubLink
  *                             node's sub-select.  The column number is contained in the
@@ -165,12 +162,18 @@ typedef struct Const
  *                             PARAM_EXEC during planning.)
  * ----------------
  */
+typedef enum ParamKind
+{
+       PARAM_EXTERN,
+       PARAM_EXEC,
+       PARAM_SUBLINK
+} ParamKind;
+
 typedef struct Param
 {
        Expr            xpr;
-       int                     paramkind;              /* kind of parameter. See above */
-       AttrNumber      paramid;                /* numeric ID for parameter ("$1") */
-       char       *paramname;          /* name for parameter ("$.foo") */
+       ParamKind       paramkind;              /* kind of parameter. See above */
+       int                     paramid;                /* numeric ID for parameter */
        Oid                     paramtype;              /* PG_TYPE OID of parameter's datatype */
 } Param;
 
index 8a82a42fbe6be756e8ffc0cf06e8ac5a18a226e6..ee30902dedbe01feae731ca034846f8c74e25fbb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.163 2006/04/04 19:35:37 tgl Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.164 2006/04/22 01:26:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3786,24 +3786,27 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
         * back for subscript evaluation, and so there can be a need to have more
         * than one active param list.
         */
-       paramLI = (ParamListInfo)
-               MemoryContextAlloc(econtext->ecxt_per_tuple_memory,
-                                                  (expr->nparams + 1) * sizeof(ParamListInfoData));
-
-       /*
-        * Put the parameter values into the parameter list entries.
-        */
-       for (i = 0; i < expr->nparams; i++)
+       if (expr->nparams > 0)
        {
-               PLpgSQL_datum *datum = estate->datums[expr->params[i]];
+               /* sizeof(ParamListInfoData) includes the first array element */
+               paramLI = (ParamListInfo)
+                       MemoryContextAlloc(econtext->ecxt_per_tuple_memory,
+                                                          sizeof(ParamListInfoData) +
+                                                          (expr->nparams - 1) * sizeof(ParamExternData));
+               paramLI->numParams = expr->nparams;
+
+               for (i = 0; i < expr->nparams; i++)
+               {
+                       ParamExternData *prm = &paramLI->params[i];
+                       PLpgSQL_datum *datum = estate->datums[expr->params[i]];
 
-               paramLI[i].kind = PARAM_NUM;
-               paramLI[i].id = i + 1;
-               exec_eval_datum(estate, datum, expr->plan_argtypes[i],
-                                               &paramLI[i].ptype,
-                                               &paramLI[i].value, &paramLI[i].isnull);
+                       exec_eval_datum(estate, datum, expr->plan_argtypes[i],
+                                                       &prm->ptype,
+                                                       &prm->value, &prm->isnull);
+               }
        }
-       paramLI[i].kind = PARAM_INVALID;
+       else
+               paramLI = NULL;
 
        /*
         * Now we can safely make the econtext point to the param list.