]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add a paramtypmod field to Param nodes. This is dead weight for Params
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 10 Dec 2006 22:13:27 +0000 (22:13 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 10 Dec 2006 22:13:27 +0000 (22:13 +0000)
representing externally-supplied values, since the APIs that carry such
values only specify type not typmod.  However, for PARAM_SUBLINK Params
it is handy to carry the typmod of the sublink's output column.  This
is a much cleaner solution for the recently reported 'could not find
pathkey item to sort' and 'failed to find unique expression in subplan
tlist' bugs than my original 8.2-compatible patch.  Besides, someday we
might want to support typmods for external parameters ...

src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/subselect.c
src/backend/parser/parse_agg.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/include/catalog/catversion.h
src/include/nodes/primnodes.h

index c1858e6746d101f47547a1ab4e67c32898c1f372..5047dc8ad7bc2979bc2f1b3fd97c7a99b80be9c5 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.353 2006/11/05 22:42:08 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.354 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -745,6 +745,7 @@ _copyParam(Param *from)
        COPY_SCALAR_FIELD(paramkind);
        COPY_SCALAR_FIELD(paramid);
        COPY_SCALAR_FIELD(paramtype);
+       COPY_SCALAR_FIELD(paramtypmod);
 
        return newnode;
 }
index a42afb77a3da11e9c124becb7da6a81fb90e00de..e341b74f3e6369505f59224e6cc750dbe25188aa 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.287 2006/11/05 22:42:08 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.288 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -147,6 +147,7 @@ _equalParam(Param *a, Param *b)
        COMPARE_SCALAR_FIELD(paramkind);
        COMPARE_SCALAR_FIELD(paramid);
        COMPARE_SCALAR_FIELD(paramtype);
+       COMPARE_SCALAR_FIELD(paramtypmod);
 
        return true;
 }
index cbffa3a3a47011f81ad51d71275fbedaa34ed015..daeb3fe872d08fb756a0c6e6a02d758ff14e8bd7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.285 2006/09/19 22:49:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.286 2006/12/10 22:13:26 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -634,6 +634,7 @@ _outParam(StringInfo str, Param *node)
        WRITE_ENUM_FIELD(paramkind, ParamKind);
        WRITE_INT_FIELD(paramid);
        WRITE_OID_FIELD(paramtype);
+       WRITE_INT_FIELD(paramtypmod);
 }
 
 static void
index ab66fc6ac891a5690809ca50860beaf51ef82005..df0a2170272ed696378334739dca0c02c534d756 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.195 2006/08/12 02:52:04 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.196 2006/12/10 22:13:26 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -337,6 +337,7 @@ _readParam(void)
        READ_ENUM_FIELD(paramkind, ParamKind);
        READ_INT_FIELD(paramid);
        READ_OID_FIELD(paramtype);
+       READ_INT_FIELD(paramtypmod);
 
        READ_DONE();
 }
index 72b986002dd359d3a240a22a3d5637eaf9c058d7..7793d071cda49010ac3a702be5309cb80c54caee 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.113 2006/12/06 19:40:01 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.114 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,7 +75,6 @@ typedef struct convert_testexpr_context
 {
        int                     rtindex;                /* RT index for Vars, or 0 for Params */
        List       *righthandIds;       /* accumulated list of Vars or Param IDs */
-       List       *sub_tlist;          /* subselect targetlist (if given) */
 } convert_testexpr_context;
 
 typedef struct finalize_primnode_context
@@ -87,8 +86,7 @@ typedef struct finalize_primnode_context
 
 static Node *convert_testexpr(Node *testexpr,
                                 int rtindex,
-                                List **righthandIds,
-                                List *sub_tlist);
+                                List **righthandIds);
 static Node *convert_testexpr_mutator(Node *node,
                                                 convert_testexpr_context *context);
 static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
@@ -166,6 +164,7 @@ replace_outer_var(Var *var)
        retval->paramkind = PARAM_EXEC;
        retval->paramid = i;
        retval->paramtype = var->vartype;
+       retval->paramtypmod = var->vartypmod;
 
        return retval;
 }
@@ -204,6 +203,7 @@ replace_outer_agg(Aggref *agg)
        retval->paramkind = PARAM_EXEC;
        retval->paramid = i;
        retval->paramtype = agg->aggtype;
+       retval->paramtypmod = -1;
 
        return retval;
 }
@@ -212,8 +212,6 @@ replace_outer_agg(Aggref *agg)
  * Generate a new Param node that will not conflict with any other.
  *
  * This is used to allocate PARAM_EXEC slots for subplan outputs.
- *
- * paramtypmod is currently unused but might be wanted someday.
  */
 static Param *
 generate_new_param(Oid paramtype, int32 paramtypmod)
@@ -225,6 +223,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
        retval->paramkind = PARAM_EXEC;
        retval->paramid = list_length(PlannerParamList);
        retval->paramtype = paramtype;
+       retval->paramtypmod = paramtypmod;
 
        pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
        pitem->item = (Node *) retval;
@@ -371,7 +370,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                if (!OidIsValid(arraytype))
                        elog(ERROR, "could not find array type for datatype %s",
                                 format_type_be(exprType((Node *) te->expr)));
-               prm = generate_new_param(arraytype, -1);
+               prm = generate_new_param(arraytype, exprTypmod((Node *) te->expr));
                node->setParam = list_make1_int(prm->paramid);
                PlannerInitPlan = lappend(PlannerInitPlan, node);
                result = (Node *) prm;
@@ -381,8 +380,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                /* Adjust the Params */
                result = convert_testexpr(testexpr,
                                                                  0,
-                                                                 &node->paramIds,
-                                                                 NIL);
+                                                                 &node->paramIds);
                node->setParam = list_copy(node->paramIds);
                PlannerInitPlan = lappend(PlannerInitPlan, node);
 
@@ -399,8 +397,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                /* Adjust the Params */
                node->testexpr = convert_testexpr(testexpr,
                                                                                  0,
-                                                                                 &node->paramIds,
-                                                                                 NIL);
+                                                                                 &node->paramIds);
 
                /*
                 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
@@ -474,10 +471,6 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
  * of the Var nodes are returned in *righthandIds (this is a bit of a type
  * cheat, but we can get away with it).
  *
- * The subquery targetlist need be supplied only if rtindex is not 0.
- * We consult it to extract the correct typmods for the created Vars.
- * (XXX this is a kluge that could go away if Params carried typmod.)
- *
  * The given testexpr has already been recursively processed by
  * process_sublinks_mutator.  Hence it can no longer contain any
  * PARAM_SUBLINK Params for lower SubLink nodes; we can safely assume that
@@ -486,15 +479,13 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
 static Node *
 convert_testexpr(Node *testexpr,
                                 int rtindex,
-                                List **righthandIds,
-                                List *sub_tlist)
+                                List **righthandIds)
 {
        Node       *result;
        convert_testexpr_context context;
 
        context.rtindex = rtindex;
        context.righthandIds = NIL;
-       context.sub_tlist = sub_tlist;
        result = convert_testexpr_mutator(testexpr, &context);
        *righthandIds = context.righthandIds;
        return result;
@@ -526,23 +517,10 @@ convert_testexpr_mutator(Node *node,
                                /* Make the Var node representing the subplan's result */
                                Var                *newvar;
 
-                               /*
-                                * XXX kluge: since Params don't carry typmod, we have to
-                                * look into the subquery targetlist to find out the right
-                                * typmod to assign to the Var.
-                                */
-                               TargetEntry *ste = get_tle_by_resno(context->sub_tlist,
-                                                                                                       param->paramid);
-
-                               if (ste == NULL || ste->resjunk)
-                                       elog(ERROR, "subquery output %d not found",
-                                                param->paramid);
-                               Assert(param->paramtype == exprType((Node *) ste->expr));
-
                                newvar = makeVar(context->rtindex,
                                                                 param->paramid,
                                                                 param->paramtype,
-                                                                exprTypmod((Node *) ste->expr),
+                                                                param->paramtypmod,
                                                                 0);
 
                                /*
@@ -558,7 +536,8 @@ convert_testexpr_mutator(Node *node,
                                /* Make the Param node representing the subplan's result */
                                Param      *newparam;
 
-                               newparam = generate_new_param(param->paramtype, -1);
+                               newparam = generate_new_param(param->paramtype,
+                                                                                         param->paramtypmod);
                                /* Record its ID */
                                context->righthandIds = lappend_int(context->righthandIds,
                                                                                                        newparam->paramid);
@@ -775,8 +754,7 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
         */
        return convert_testexpr(sublink->testexpr,
                                                        rtindex,
-                                                       &ininfo->sub_targetlist,
-                                                       subselect->targetList);
+                                                       &ininfo->sub_targetlist);
 }
 
 /*
index 3bda907c994a592efe81a7b09089e3c582e1495e..438d7398c32f86fa4beb90b47dcba53f7859aad7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.73 2006/07/27 19:52:05 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.74 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -394,6 +394,7 @@ build_aggregate_fnexprs(Oid *agg_input_types,
        argp->paramkind = PARAM_EXEC;
        argp->paramid = -1;
        argp->paramtype = agg_state_type;
+       argp->paramtypmod = -1;
 
        args = list_make1(argp);
 
@@ -403,6 +404,7 @@ build_aggregate_fnexprs(Oid *agg_input_types,
                argp->paramkind = PARAM_EXEC;
                argp->paramid = -1;
                argp->paramtype = agg_input_types[i];
+               argp->paramtypmod = -1;
                args = lappend(args, argp);
        }
 
@@ -425,6 +427,7 @@ build_aggregate_fnexprs(Oid *agg_input_types,
        argp->paramkind = PARAM_EXEC;
        argp->paramid = -1;
        argp->paramtype = agg_state_type;
+       argp->paramtypmod = -1;
        args = list_make1(argp);
 
        *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
index a8972342af495c1a8aa7032edbf1076c463f533c..2a468c682712c3d354f85b070755802af601723d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.146 2006/11/28 12:54:41 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.147 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -264,6 +264,14 @@ coerce_type(ParseState *pstate, Node *node,
                }
 
                param->paramtype = targetTypeId;
+               /*
+                * Note: it is tempting here to set the Param's paramtypmod to
+                * targetTypeMod, but that is probably unwise because we have no
+                * infrastructure that enforces that the value delivered for a
+                * Param will match any particular typmod.  Leaving it -1 ensures
+                * that a run-time length check/coercion will occur if needed.
+                */
+               param->paramtypmod = -1;
 
                return (Node *) param;
        }
index 7c72ae9e22a7ba4ccca28719e1e10bbae3a83667..b1b6ea81456a9babde1f6ecd2808147aeaaf57be 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.198 2006/10/04 00:29:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.199 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -572,6 +572,7 @@ transformParamRef(ParseState *pstate, ParamRef *pref)
        param->paramkind = PARAM_EXTERN;
        param->paramid = paramno;
        param->paramtype = toppstate->p_paramtypes[paramno - 1];
+       param->paramtypmod = -1;
 
        return (Node *) param;
 }
@@ -1180,6 +1181,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
                        param->paramkind = PARAM_SUBLINK;
                        param->paramid = tent->resno;
                        param->paramtype = exprType((Node *) tent->expr);
+                       param->paramtypmod = exprTypmod((Node *) tent->expr);
 
                        right_list = lappend(right_list, param);
                }
@@ -1721,6 +1723,8 @@ exprTypmod(Node *expr)
                                }
                        }
                        break;
+               case T_Param:
+                       return ((Param *) expr)->paramtypmod;
                case T_FuncExpr:
                        {
                                int32           coercedTypmod;
index 246eef42f4febbb442f4adf5bb9dfc48c230aac4..e6bcdfb054e0b8c38b0e78738b5da595ce0070b6 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.361 2006/12/06 18:06:47 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.362 2006/12/10 22:13:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200612061
+#define CATALOG_VERSION_NO     200612101
 
 #endif
index 841d85336e75d1f983aee106e81a0bf76be5e920..6c5e761275e484a27901aa5a857ead3cfb37fcfc 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.117 2006/10/04 00:30:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.118 2006/12/10 22:13:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -113,7 +113,7 @@ typedef struct Var
                                                                 * table (could also be INNER or OUTER) */
        AttrNumber      varattno;               /* attribute number of this var, or zero for
                                                                 * all */
-       Oid                     vartype;                /* pg_type tuple OID for the type of this var */
+       Oid                     vartype;                /* pg_type OID for the type of this var */
        int32           vartypmod;              /* pg_attribute typmod value */
        Index           varlevelsup;
 
@@ -159,6 +159,11 @@ typedef struct Const
  *                             node's sub-select.  The column number is contained in the
  *                             `paramid' field.  (This type of Param is converted to
  *                             PARAM_EXEC during planning.)
+ *
+ * Note: currently, paramtypmod is valid for PARAM_SUBLINK Params, and for
+ * PARAM_EXEC Params generated from them; it is always -1 for PARAM_EXTERN
+ * params, since the APIs that supply values for such parameters don't carry
+ * any typmod info.
  * ----------------
  */
 typedef enum ParamKind
@@ -173,7 +178,8 @@ typedef struct Param
        Expr            xpr;
        ParamKind       paramkind;              /* kind of parameter. See above */
        int                     paramid;                /* numeric ID for parameter */
-       Oid                     paramtype;              /* PG_TYPE OID of parameter's datatype */
+       Oid                     paramtype;              /* pg_type OID of parameter's datatype */
+       int32           paramtypmod;    /* typmod value, if known */
 } Param;
 
 /*