]> granicus.if.org Git - postgresql/commitdiff
Fix another place that wasn't maintaining AND/OR flatness of an
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 Jan 2004 22:20:28 +0000 (22:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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,