Fix another place that wasn't maintaining AND/OR flatness of an
authorTom Lane
Mon, 12 Jan 2004 22:20:28 +0000 (22:20 +0000)
committerTom Lane
Mon, 12 Jan 2004 22:20:28 +0000 (22:20 +0000)
already-canonicalized qual expression.

src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/subselect.c

index bf8a28d12546aeba201cd8b72de6169e5fb56c0a..7af46244bbb629ea5e8c4251217dd89ad7a008f3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.163 2003/12/28 21:57:36 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.164 2004/01/12 22:20:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -380,6 +380,10 @@ preprocess_expression(Query *parse, Node *expr, int kind)
     * If it's a qual or havingQual, canonicalize it.  It seems most useful
     * to do this before applying eval_const_expressions, since the latter
     * can optimize flattened AND/ORs better than unflattened ones.
+    *
+    * Note: all processing of a qual expression after this point must be
+    * careful to maintain AND/OR flatness --- that is, do not generate a
+    * tree with AND directly under AND, nor OR directly under OR.
     */
    if (kind == EXPRKIND_QUAL)
    {
@@ -396,14 +400,6 @@ preprocess_expression(Query *parse, Node *expr, int kind)
     */
    expr = eval_const_expressions(expr);
 
-   /*
-    * If it's a qual or havingQual, convert it to implicit-AND format.
-    * (We don't want to do this before eval_const_expressions, since the
-    * latter would be unable to simplify a top-level AND correctly.)
-    */
-   if (kind == EXPRKIND_QUAL)
-       expr = (Node *) make_ands_implicit((Expr *) expr);
-
    /* Expand SubLinks to SubPlans */
    if (parse->hasSubLinks)
        expr = SS_process_sublinks(expr, (kind == EXPRKIND_QUAL));
@@ -417,6 +413,15 @@ preprocess_expression(Query *parse, Node *expr, int kind)
    if (PlannerQueryLevel > 1)
        expr = SS_replace_correlation_vars(expr);
 
+   /*
+    * If it's a qual or havingQual, convert it to implicit-AND format.
+    * (We don't want to do this before eval_const_expressions, since the
+    * latter would be unable to simplify a top-level AND correctly.  Also,
+    * SS_process_sublinks expects explicit-AND format.)
+    */
+   if (kind == EXPRKIND_QUAL)
+       expr = (Node *) make_ands_implicit((Expr *) expr);
+
    return expr;
 }
 
index 5140fcb52a9794e2eba9e99ebe6c953db5fdd29b..34dca0e5acaedf6a773520ba1f9ced6f241fc788 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.86 2003/11/29 19:51:50 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.87 2004/01/12 22:20:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -848,13 +848,58 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
    Assert(!IsA(node, Query));
 
    /*
-    * If we recurse down through anything other than a List node, we are
-    * definitely not at top qual level anymore.
+    * Because make_subplan() could return an AND or OR clause, we have to
+    * take steps to preserve AND/OR flatness of a qual.  We assume the input
+    * has been AND/OR flattened and so we need no recursion here.
+    *
+    * If we recurse down through anything other than an AND node,
+    * we are definitely not at top qual level anymore.  (Due to the coding
+    * here, we will not get called on the List subnodes of an AND, so no
+    * check is needed for List.)
     */
-   if (IsA(node, List))
+   if (and_clause(node))
+   {
+       List   *newargs = NIL;
+       List   *l;
+
+       /* Still at qual top-level */
        locTopQual = *isTopQual;
-   else
-       locTopQual = false;
+
+       foreach(l, ((BoolExpr *) node)->args)
+       {
+           Node *newarg;
+
+           newarg = process_sublinks_mutator(lfirst(l),
+                                             (void *) &locTopQual);
+           if (and_clause(newarg))
+               newargs = nconc(newargs, ((BoolExpr *) newarg)->args);
+           else
+               newargs = lappend(newargs, newarg);
+       }
+       return (Node *) make_andclause(newargs);
+   }
+
+   /* otherwise not at qual top-level */
+   locTopQual = false;
+
+   if (or_clause(node))
+   {
+       List   *newargs = NIL;
+       List   *l;
+
+       foreach(l, ((BoolExpr *) node)->args)
+       {
+           Node *newarg;
+
+           newarg = process_sublinks_mutator(lfirst(l),
+                                             (void *) &locTopQual);
+           if (or_clause(newarg))
+               newargs = nconc(newargs, ((BoolExpr *) newarg)->args);
+           else
+               newargs = lappend(newargs, newarg);
+       }
+       return (Node *) make_orclause(newargs);
+   }
 
    return expression_tree_mutator(node,
                                   process_sublinks_mutator,