mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
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 ...
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user