From: Tom Lane Date: Wed, 6 Dec 2006 19:40:01 +0000 (+0000) Subject: Fix planning of SubLinks to ensure that Vars generated from transformation of X-Git-Tag: REL9_0_0~6576 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b307d7a6c4af2de8b6b25d5614152f7cd4378f03;p=pg-rex%2Fsyncrep.git Fix planning of SubLinks to ensure that Vars generated from transformation of a sublink's test expression have the correct vartypmod, rather than defaulting to -1. There's at least one place where this is important because we're expecting these Vars to be exactly equal() to those appearing in the subplan itself. This is a pretty klugy solution --- it would likely be cleaner to change Param nodes to include a typmod field --- but we can't do that in the already-released 8.2 branch. Per bug report from Hubert Fongarnand. --- diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 94c97a55aa..72b986002d 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -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.112 2006/10/04 00:29:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.113 2006/12/06 19:40:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -75,6 +75,7 @@ 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 @@ -86,7 +87,8 @@ typedef struct finalize_primnode_context static Node *convert_testexpr(Node *testexpr, int rtindex, - List **righthandIds); + List **righthandIds, + List *sub_tlist); static Node *convert_testexpr_mutator(Node *node, convert_testexpr_context *context); static bool subplan_is_hashable(SubLink *slink, SubPlan *node); @@ -379,7 +381,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) /* Adjust the Params */ result = convert_testexpr(testexpr, 0, - &node->paramIds); + &node->paramIds, + NIL); node->setParam = list_copy(node->paramIds); PlannerInitPlan = lappend(PlannerInitPlan, node); @@ -396,7 +399,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) /* Adjust the Params */ node->testexpr = convert_testexpr(testexpr, 0, - &node->paramIds); + &node->paramIds, + NIL); /* * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to @@ -470,6 +474,10 @@ 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 @@ -478,13 +486,15 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual) static Node * convert_testexpr(Node *testexpr, int rtindex, - List **righthandIds) + List **righthandIds, + List *sub_tlist) { 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; @@ -516,10 +526,23 @@ 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, - -1, + exprTypmod((Node *) ste->expr), 0); /* @@ -752,7 +775,8 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink) */ return convert_testexpr(sublink->testexpr, rtindex, - &ininfo->sub_targetlist); + &ininfo->sub_targetlist, + subselect->targetList); } /*