提交 9fa12ddd 编写于 作者: T Tom Lane

Add a paramtypmod field to Param nodes. This is dead weight for Params

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 ...
上级 314c7b64
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -745,6 +745,7 @@ _copyParam(Param *from)
COPY_SCALAR_FIELD(paramkind); COPY_SCALAR_FIELD(paramkind);
COPY_SCALAR_FIELD(paramid); COPY_SCALAR_FIELD(paramid);
COPY_SCALAR_FIELD(paramtype); COPY_SCALAR_FIELD(paramtype);
COPY_SCALAR_FIELD(paramtypmod);
return newnode; return newnode;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -147,6 +147,7 @@ _equalParam(Param *a, Param *b)
COMPARE_SCALAR_FIELD(paramkind); COMPARE_SCALAR_FIELD(paramkind);
COMPARE_SCALAR_FIELD(paramid); COMPARE_SCALAR_FIELD(paramid);
COMPARE_SCALAR_FIELD(paramtype); COMPARE_SCALAR_FIELD(paramtype);
COMPARE_SCALAR_FIELD(paramtypmod);
return true; return true;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -634,6 +634,7 @@ _outParam(StringInfo str, Param *node) ...@@ -634,6 +634,7 @@ _outParam(StringInfo str, Param *node)
WRITE_ENUM_FIELD(paramkind, ParamKind); WRITE_ENUM_FIELD(paramkind, ParamKind);
WRITE_INT_FIELD(paramid); WRITE_INT_FIELD(paramid);
WRITE_OID_FIELD(paramtype); WRITE_OID_FIELD(paramtype);
WRITE_INT_FIELD(paramtypmod);
} }
static void static void
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
...@@ -337,6 +337,7 @@ _readParam(void) ...@@ -337,6 +337,7 @@ _readParam(void)
READ_ENUM_FIELD(paramkind, ParamKind); READ_ENUM_FIELD(paramkind, ParamKind);
READ_INT_FIELD(paramid); READ_INT_FIELD(paramid);
READ_OID_FIELD(paramtype); READ_OID_FIELD(paramtype);
READ_INT_FIELD(paramtypmod);
READ_DONE(); READ_DONE();
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 ...@@ -75,7 +75,6 @@ typedef struct convert_testexpr_context
{ {
int rtindex; /* RT index for Vars, or 0 for Params */ int rtindex; /* RT index for Vars, or 0 for Params */
List *righthandIds; /* accumulated list of Vars or Param IDs */ List *righthandIds; /* accumulated list of Vars or Param IDs */
List *sub_tlist; /* subselect targetlist (if given) */
} convert_testexpr_context; } convert_testexpr_context;
typedef struct finalize_primnode_context typedef struct finalize_primnode_context
...@@ -87,8 +86,7 @@ typedef struct finalize_primnode_context ...@@ -87,8 +86,7 @@ typedef struct finalize_primnode_context
static Node *convert_testexpr(Node *testexpr, static Node *convert_testexpr(Node *testexpr,
int rtindex, int rtindex,
List **righthandIds, List **righthandIds);
List *sub_tlist);
static Node *convert_testexpr_mutator(Node *node, static Node *convert_testexpr_mutator(Node *node,
convert_testexpr_context *context); convert_testexpr_context *context);
static bool subplan_is_hashable(SubLink *slink, SubPlan *node); static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
...@@ -166,6 +164,7 @@ replace_outer_var(Var *var) ...@@ -166,6 +164,7 @@ replace_outer_var(Var *var)
retval->paramkind = PARAM_EXEC; retval->paramkind = PARAM_EXEC;
retval->paramid = i; retval->paramid = i;
retval->paramtype = var->vartype; retval->paramtype = var->vartype;
retval->paramtypmod = var->vartypmod;
return retval; return retval;
} }
...@@ -204,6 +203,7 @@ replace_outer_agg(Aggref *agg) ...@@ -204,6 +203,7 @@ replace_outer_agg(Aggref *agg)
retval->paramkind = PARAM_EXEC; retval->paramkind = PARAM_EXEC;
retval->paramid = i; retval->paramid = i;
retval->paramtype = agg->aggtype; retval->paramtype = agg->aggtype;
retval->paramtypmod = -1;
return retval; return retval;
} }
...@@ -212,8 +212,6 @@ replace_outer_agg(Aggref *agg) ...@@ -212,8 +212,6 @@ replace_outer_agg(Aggref *agg)
* Generate a new Param node that will not conflict with any other. * Generate a new Param node that will not conflict with any other.
* *
* This is used to allocate PARAM_EXEC slots for subplan outputs. * This is used to allocate PARAM_EXEC slots for subplan outputs.
*
* paramtypmod is currently unused but might be wanted someday.
*/ */
static Param * static Param *
generate_new_param(Oid paramtype, int32 paramtypmod) generate_new_param(Oid paramtype, int32 paramtypmod)
...@@ -225,6 +223,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod) ...@@ -225,6 +223,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
retval->paramkind = PARAM_EXEC; retval->paramkind = PARAM_EXEC;
retval->paramid = list_length(PlannerParamList); retval->paramid = list_length(PlannerParamList);
retval->paramtype = paramtype; retval->paramtype = paramtype;
retval->paramtypmod = paramtypmod;
pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem)); pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
pitem->item = (Node *) retval; pitem->item = (Node *) retval;
...@@ -371,7 +370,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) ...@@ -371,7 +370,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
if (!OidIsValid(arraytype)) if (!OidIsValid(arraytype))
elog(ERROR, "could not find array type for datatype %s", elog(ERROR, "could not find array type for datatype %s",
format_type_be(exprType((Node *) te->expr))); 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); node->setParam = list_make1_int(prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node); PlannerInitPlan = lappend(PlannerInitPlan, node);
result = (Node *) prm; result = (Node *) prm;
...@@ -381,8 +380,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) ...@@ -381,8 +380,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
/* Adjust the Params */ /* Adjust the Params */
result = convert_testexpr(testexpr, result = convert_testexpr(testexpr,
0, 0,
&node->paramIds, &node->paramIds);
NIL);
node->setParam = list_copy(node->paramIds); node->setParam = list_copy(node->paramIds);
PlannerInitPlan = lappend(PlannerInitPlan, node); PlannerInitPlan = lappend(PlannerInitPlan, node);
...@@ -399,8 +397,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) ...@@ -399,8 +397,7 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
/* Adjust the Params */ /* Adjust the Params */
node->testexpr = convert_testexpr(testexpr, node->testexpr = convert_testexpr(testexpr,
0, 0,
&node->paramIds, &node->paramIds);
NIL);
/* /*
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to * 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) ...@@ -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 * of the Var nodes are returned in *righthandIds (this is a bit of a type
* cheat, but we can get away with it). * 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 * The given testexpr has already been recursively processed by
* process_sublinks_mutator. Hence it can no longer contain any * process_sublinks_mutator. Hence it can no longer contain any
* PARAM_SUBLINK Params for lower SubLink nodes; we can safely assume that * PARAM_SUBLINK Params for lower SubLink nodes; we can safely assume that
...@@ -486,15 +479,13 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) ...@@ -486,15 +479,13 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
static Node * static Node *
convert_testexpr(Node *testexpr, convert_testexpr(Node *testexpr,
int rtindex, int rtindex,
List **righthandIds, List **righthandIds)
List *sub_tlist)
{ {
Node *result; Node *result;
convert_testexpr_context context; convert_testexpr_context context;
context.rtindex = rtindex; context.rtindex = rtindex;
context.righthandIds = NIL; context.righthandIds = NIL;
context.sub_tlist = sub_tlist;
result = convert_testexpr_mutator(testexpr, &context); result = convert_testexpr_mutator(testexpr, &context);
*righthandIds = context.righthandIds; *righthandIds = context.righthandIds;
return result; return result;
...@@ -526,23 +517,10 @@ convert_testexpr_mutator(Node *node, ...@@ -526,23 +517,10 @@ convert_testexpr_mutator(Node *node,
/* Make the Var node representing the subplan's result */ /* Make the Var node representing the subplan's result */
Var *newvar; 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, newvar = makeVar(context->rtindex,
param->paramid, param->paramid,
param->paramtype, param->paramtype,
exprTypmod((Node *) ste->expr), param->paramtypmod,
0); 0);
/* /*
...@@ -558,7 +536,8 @@ convert_testexpr_mutator(Node *node, ...@@ -558,7 +536,8 @@ convert_testexpr_mutator(Node *node,
/* Make the Param node representing the subplan's result */ /* Make the Param node representing the subplan's result */
Param *newparam; Param *newparam;
newparam = generate_new_param(param->paramtype, -1); newparam = generate_new_param(param->paramtype,
param->paramtypmod);
/* Record its ID */ /* Record its ID */
context->righthandIds = lappend_int(context->righthandIds, context->righthandIds = lappend_int(context->righthandIds,
newparam->paramid); newparam->paramid);
...@@ -775,8 +754,7 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink) ...@@ -775,8 +754,7 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
*/ */
return convert_testexpr(sublink->testexpr, return convert_testexpr(sublink->testexpr,
rtindex, rtindex,
&ininfo->sub_targetlist, &ininfo->sub_targetlist);
subselect->targetList);
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -394,6 +394,7 @@ build_aggregate_fnexprs(Oid *agg_input_types,
argp->paramkind = PARAM_EXEC; argp->paramkind = PARAM_EXEC;
argp->paramid = -1; argp->paramid = -1;
argp->paramtype = agg_state_type; argp->paramtype = agg_state_type;
argp->paramtypmod = -1;
args = list_make1(argp); args = list_make1(argp);
...@@ -403,6 +404,7 @@ build_aggregate_fnexprs(Oid *agg_input_types, ...@@ -403,6 +404,7 @@ build_aggregate_fnexprs(Oid *agg_input_types,
argp->paramkind = PARAM_EXEC; argp->paramkind = PARAM_EXEC;
argp->paramid = -1; argp->paramid = -1;
argp->paramtype = agg_input_types[i]; argp->paramtype = agg_input_types[i];
argp->paramtypmod = -1;
args = lappend(args, argp); args = lappend(args, argp);
} }
...@@ -425,6 +427,7 @@ build_aggregate_fnexprs(Oid *agg_input_types, ...@@ -425,6 +427,7 @@ build_aggregate_fnexprs(Oid *agg_input_types,
argp->paramkind = PARAM_EXEC; argp->paramkind = PARAM_EXEC;
argp->paramid = -1; argp->paramid = -1;
argp->paramtype = agg_state_type; argp->paramtype = agg_state_type;
argp->paramtypmod = -1;
args = list_make1(argp); args = list_make1(argp);
*finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid, *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -264,6 +264,14 @@ coerce_type(ParseState *pstate, Node *node,
} }
param->paramtype = targetTypeId; 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; return (Node *) param;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -572,6 +572,7 @@ transformParamRef(ParseState *pstate, ParamRef *pref)
param->paramkind = PARAM_EXTERN; param->paramkind = PARAM_EXTERN;
param->paramid = paramno; param->paramid = paramno;
param->paramtype = toppstate->p_paramtypes[paramno - 1]; param->paramtype = toppstate->p_paramtypes[paramno - 1];
param->paramtypmod = -1;
return (Node *) param; return (Node *) param;
} }
...@@ -1180,6 +1181,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink) ...@@ -1180,6 +1181,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
param->paramkind = PARAM_SUBLINK; param->paramkind = PARAM_SUBLINK;
param->paramid = tent->resno; param->paramid = tent->resno;
param->paramtype = exprType((Node *) tent->expr); param->paramtype = exprType((Node *) tent->expr);
param->paramtypmod = exprTypmod((Node *) tent->expr);
right_list = lappend(right_list, param); right_list = lappend(right_list, param);
} }
...@@ -1721,6 +1723,8 @@ exprTypmod(Node *expr) ...@@ -1721,6 +1723,8 @@ exprTypmod(Node *expr)
} }
} }
break; break;
case T_Param:
return ((Param *) expr)->paramtypmod;
case T_FuncExpr: case T_FuncExpr:
{ {
int32 coercedTypmod; int32 coercedTypmod;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200612061 #define CATALOG_VERSION_NO 200612101
#endif #endif
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -113,7 +113,7 @@ typedef struct Var
* table (could also be INNER or OUTER) */ * table (could also be INNER or OUTER) */
AttrNumber varattno; /* attribute number of this var, or zero for AttrNumber varattno; /* attribute number of this var, or zero for
* all */ * 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 */ int32 vartypmod; /* pg_attribute typmod value */
Index varlevelsup; Index varlevelsup;
...@@ -159,6 +159,11 @@ typedef struct Const ...@@ -159,6 +159,11 @@ typedef struct Const
* node's sub-select. The column number is contained in the * node's sub-select. The column number is contained in the
* `paramid' field. (This type of Param is converted to * `paramid' field. (This type of Param is converted to
* PARAM_EXEC during planning.) * 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 typedef enum ParamKind
...@@ -173,7 +178,8 @@ typedef struct Param ...@@ -173,7 +178,8 @@ typedef struct Param
Expr xpr; Expr xpr;
ParamKind paramkind; /* kind of parameter. See above */ ParamKind paramkind; /* kind of parameter. See above */
int paramid; /* numeric ID for parameter */ 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; } Param;
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册