OSDN Git Service

Fix planning of SubLinks to ensure that Vars generated from transformation of
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 6 Dec 2006 19:40:01 +0000 (19:40 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 6 Dec 2006 19:40:01 +0000 (19:40 +0000)
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.

src/backend/optimizer/plan/subselect.c

index 94c97a5..72b9860 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.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);
 }
 
 /*