Reconsider mechanism for marking sub-selects that are at top level of
authorTom Lane
Mon, 13 Jan 2003 18:10:53 +0000 (18:10 +0000)
committerTom Lane
Mon, 13 Jan 2003 18:10:53 +0000 (18:10 +0000)
a qualification clause (and hence can get away with being sloppy about
distinguishing FALSE from UNKNOWN).  We need to know this in subselect.c;
marking the subplans in setrefs.c is too late.

src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/include/optimizer/subselect.h

index 3b8981021af82d23fd9a52bb1532dfc4d1ec0854..76a16cd833d64cf7ac1198b4e4861c5a1f747120 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.137 2003/01/13 00:29:25 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.138 2003/01/13 18:10:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -777,7 +777,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
 
    /* Expand SubLinks to SubPlans */
    if (parse->hasSubLinks)
-       expr = SS_process_sublinks(expr);
+       expr = SS_process_sublinks(expr, (kind != EXPRKIND_TARGET));
 
    /* Replace uplevel vars with Param nodes */
    if (PlannerQueryLevel > 1)
index c76d67b93e5191986b3db2125dc54b1a6cefd3f2..1b5c72e163c43e78d757944ab015a899aa514277 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.87 2003/01/10 21:08:11 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.88 2003/01/13 18:10:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,7 +42,6 @@ typedef struct
 
 static void fix_expr_references(Plan *plan, Node *node);
 static bool fix_expr_references_walker(Node *node, void *context);
-static void mark_qual_expressions(List *quals);
 static void set_join_references(Join *join, List *rtable);
 static void set_uppernode_references(Plan *plan, Index subvarno);
 static Node *join_references_mutator(Node *node,
@@ -89,12 +88,10 @@ set_plan_references(Plan *plan, List *rtable)
        case T_SeqScan:
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            break;
        case T_IndexScan:
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            fix_expr_references(plan,
                                (Node *) ((IndexScan *) plan)->indxqual);
            fix_expr_references(plan,
@@ -103,7 +100,6 @@ set_plan_references(Plan *plan, List *rtable)
        case T_TidScan:
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            fix_expr_references(plan,
                                (Node *) ((TidScan *) plan)->tideval);
            break;
@@ -118,7 +114,6 @@ set_plan_references(Plan *plan, List *rtable)
                 */
                fix_expr_references(plan, (Node *) plan->targetlist);
                fix_expr_references(plan, (Node *) plan->qual);
-               mark_qual_expressions(plan->qual);
 
                /* Recurse into subplan too */
                rte = rt_fetch(((SubqueryScan *) plan)->scan.scanrelid,
@@ -134,7 +129,6 @@ set_plan_references(Plan *plan, List *rtable)
 
                fix_expr_references(plan, (Node *) plan->targetlist);
                fix_expr_references(plan, (Node *) plan->qual);
-               mark_qual_expressions(plan->qual);
                rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
                               rtable);
                Assert(rte->rtekind == RTE_FUNCTION);
@@ -145,17 +139,13 @@ set_plan_references(Plan *plan, List *rtable)
            set_join_references((Join *) plan, rtable);
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
-           mark_qual_expressions(((Join *) plan)->joinqual);
            break;
        case T_MergeJoin:
            set_join_references((Join *) plan, rtable);
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
-           mark_qual_expressions(((Join *) plan)->joinqual);
            fix_expr_references(plan,
                            (Node *) ((MergeJoin *) plan)->mergeclauses);
            break;
@@ -163,9 +153,7 @@ set_plan_references(Plan *plan, List *rtable)
            set_join_references((Join *) plan, rtable);
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
-           mark_qual_expressions(((Join *) plan)->joinqual);
            fix_expr_references(plan,
                              (Node *) ((HashJoin *) plan)->hashclauses);
            break;
@@ -192,7 +180,6 @@ set_plan_references(Plan *plan, List *rtable)
            set_uppernode_references(plan, (Index) 0);
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            break;
        case T_Result:
 
@@ -206,9 +193,7 @@ set_plan_references(Plan *plan, List *rtable)
                set_uppernode_references(plan, (Index) OUTER);
            fix_expr_references(plan, (Node *) plan->targetlist);
            fix_expr_references(plan, (Node *) plan->qual);
-           mark_qual_expressions(plan->qual);
            fix_expr_references(plan, ((Result *) plan)->resconstantqual);
-           mark_qual_expressions((List *) ((Result *) plan)->resconstantqual);
            break;
        case T_Append:
 
@@ -283,28 +268,6 @@ fix_expr_references_walker(Node *node, void *context)
    return expression_tree_walker(node, fix_expr_references_walker, context);
 }
 
-/*
- * mark_qual_expressions
- *   Do final cleanup on qualifier expressions (not targetlists!)
- *
- * SubPlans appearing at the top level of a qual expression are marked
- * to indicate that they need not distinguish UNKNOWN (null) from FALSE
- * results; this can save processing time in some cases.
- */
-static void
-mark_qual_expressions(List *quals)
-{
-   List   *qual;
-
-   foreach(qual, quals)
-   {
-       Node   *node = lfirst(qual);
-
-       if (IsA(node, SubPlan))
-           ((SubPlan *) node)->unknownEqFalse = true;
-   }
-}
-
 /*
  * set_join_references
  *   Modifies the target list of a join node to reference its subplans,
index 42da081e0596f9890c0fb9f8cb5b3e505c4c66e9..3c72199777eefb7c507b3f9800bad5c6f448ad65 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.65 2003/01/13 00:29:26 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.66 2003/01/13 18:10:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -65,7 +65,7 @@ static List *convert_sublink_opers(List *lefthand, List *operOids,
                                   List *targetlist, List **paramIds);
 static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
 static Node *replace_correlation_vars_mutator(Node *node, void *context);
-static Node *process_sublinks_mutator(Node *node, void *context);
+static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
 static bool finalize_primnode(Node *node, finalize_primnode_results *results);
 
 
@@ -159,7 +159,8 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
  * Convert a bare SubLink (as created by the parser) into a SubPlan.
  *
  * We are given the raw SubLink and the already-processed lefthand argument
- * list (use this instead of the SubLink's own field).
+ * list (use this instead of the SubLink's own field).  We are also told if
+ * this expression appears at top level of a WHERE/HAVING qual.
  *
  * The result is whatever we need to substitute in place of the SubLink
  * node in the executable expression.  This will be either the SubPlan
@@ -168,7 +169,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
  * containing InitPlan Param nodes.
  */
 static Node *
-make_subplan(SubLink *slink, List *lefthand)
+make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
 {
    SubPlan    *node = makeNode(SubPlan);
    Query      *subquery = (Query *) (slink->subselect);
@@ -232,7 +233,8 @@ make_subplan(SubLink *slink, List *lefthand)
    node->exprs = NIL;
    node->paramIds = NIL;
    node->useHashTable = false;
-   node->unknownEqFalse = false;
+   /* At top level of a qual, can treat UNKNOWN the same as FALSE */
+   node->unknownEqFalse = isTopQual;
    node->setParam = NIL;
    node->parParam = NIL;
    node->args = NIL;
@@ -589,17 +591,23 @@ replace_correlation_vars_mutator(Node *node, void *context)
 
 /*
  * Expand SubLinks to SubPlans in the given expression.
+ *
+ * The isQual argument tells whether or not this expression is a WHERE/HAVING
+ * qualifier expression.  If it is, any sublinks appearing at top level need
+ * not distinguish FALSE from UNKNOWN return values.
  */
 Node *
-SS_process_sublinks(Node *expr)
+SS_process_sublinks(Node *expr, bool isQual)
 {
-   /* No setup needed for tree walk, so away we go */
-   return process_sublinks_mutator(expr, NULL);
+   /* The only context needed is the initial are-we-in-a-qual flag */
+   return process_sublinks_mutator(expr, &isQual);
 }
 
 static Node *
-process_sublinks_mutator(Node *node, void *context)
+process_sublinks_mutator(Node *node, bool *isTopQual)
 {
+   bool    locTopQual;
+
    if (node == NULL)
        return NULL;
    if (IsA(node, SubLink))
@@ -610,12 +618,13 @@ process_sublinks_mutator(Node *node, void *context)
        /*
         * First, recursively process the lefthand-side expressions, if any.
         */
+       locTopQual = false;
        lefthand = (List *)
-           process_sublinks_mutator((Node *) sublink->lefthand, context);
+           process_sublinks_mutator((Node *) sublink->lefthand, &locTopQual);
        /*
         * Now build the SubPlan node and make the expr to return.
         */
-       return make_subplan(sublink, lefthand);
+       return make_subplan(sublink, lefthand, *isTopQual);
    }
 
    /*
@@ -626,9 +635,18 @@ process_sublinks_mutator(Node *node, void *context)
     */
    Assert(!is_subplan(node));
 
+   /*
+    * If we recurse down through anything other than a List node, we are
+    * definitely not at top qual level anymore.
+    */
+   if (IsA(node, List))
+       locTopQual = *isTopQual;
+   else
+       locTopQual = false;
+
    return expression_tree_mutator(node,
                                   process_sublinks_mutator,
-                                  context);
+                                  (void *) &locTopQual);
 }
 
 /*
index b504cd7bee67ce5381524560154ecdb1c712a246..8fead9929f6476043befc363a2321d316448c75e 100644 (file)
@@ -16,6 +16,6 @@ extern int    PlannerPlanId;      /* to assign unique ID to subquery plans */
 
 extern List *SS_finalize_plan(Plan *plan, List *rtable);
 extern Node *SS_replace_correlation_vars(Node *expr);
-extern Node *SS_process_sublinks(Node *expr);
+extern Node *SS_process_sublinks(Node *expr, bool isQual);
 
 #endif   /* SUBSELECT_H */