Skip to content

Commit 67af5ba

Browse files
committed
Fix another place that wasn't maintaining AND/OR flatness of an
already-canonicalized qual expression.
1 parent 5590be0 commit 67af5ba

File tree

2 files changed

+65
-15
lines changed

2 files changed

+65
-15
lines changed

src/backend/optimizer/plan/planner.c

+14-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.163 2003/12/28 21:57:36 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.164 2004/01/12 22:20:28 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -380,6 +380,10 @@ preprocess_expression(Query *parse, Node *expr, int kind)
380380
* If it's a qual or havingQual, canonicalize it. It seems most useful
381381
* to do this before applying eval_const_expressions, since the latter
382382
* can optimize flattened AND/ORs better than unflattened ones.
383+
*
384+
* Note: all processing of a qual expression after this point must be
385+
* careful to maintain AND/OR flatness --- that is, do not generate a
386+
* tree with AND directly under AND, nor OR directly under OR.
383387
*/
384388
if (kind == EXPRKIND_QUAL)
385389
{
@@ -396,14 +400,6 @@ preprocess_expression(Query *parse, Node *expr, int kind)
396400
*/
397401
expr = eval_const_expressions(expr);
398402

399-
/*
400-
* If it's a qual or havingQual, convert it to implicit-AND format.
401-
* (We don't want to do this before eval_const_expressions, since the
402-
* latter would be unable to simplify a top-level AND correctly.)
403-
*/
404-
if (kind == EXPRKIND_QUAL)
405-
expr = (Node *) make_ands_implicit((Expr *) expr);
406-
407403
/* Expand SubLinks to SubPlans */
408404
if (parse->hasSubLinks)
409405
expr = SS_process_sublinks(expr, (kind == EXPRKIND_QUAL));
@@ -417,6 +413,15 @@ preprocess_expression(Query *parse, Node *expr, int kind)
417413
if (PlannerQueryLevel > 1)
418414
expr = SS_replace_correlation_vars(expr);
419415

416+
/*
417+
* If it's a qual or havingQual, convert it to implicit-AND format.
418+
* (We don't want to do this before eval_const_expressions, since the
419+
* latter would be unable to simplify a top-level AND correctly. Also,
420+
* SS_process_sublinks expects explicit-AND format.)
421+
*/
422+
if (kind == EXPRKIND_QUAL)
423+
expr = (Node *) make_ands_implicit((Expr *) expr);
424+
420425
return expr;
421426
}
422427

src/backend/optimizer/plan/subselect.c

+51-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.86 2003/11/29 19:51:50 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.87 2004/01/12 22:20:28 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -848,13 +848,58 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
848848
Assert(!IsA(node, Query));
849849

850850
/*
851-
* If we recurse down through anything other than a List node, we are
852-
* definitely not at top qual level anymore.
851+
* Because make_subplan() could return an AND or OR clause, we have to
852+
* take steps to preserve AND/OR flatness of a qual. We assume the input
853+
* has been AND/OR flattened and so we need no recursion here.
854+
*
855+
* If we recurse down through anything other than an AND node,
856+
* we are definitely not at top qual level anymore. (Due to the coding
857+
* here, we will not get called on the List subnodes of an AND, so no
858+
* check is needed for List.)
853859
*/
854-
if (IsA(node, List))
860+
if (and_clause(node))
861+
{
862+
List *newargs = NIL;
863+
List *l;
864+
865+
/* Still at qual top-level */
855866
locTopQual = *isTopQual;
856-
else
857-
locTopQual = false;
867+
868+
foreach(l, ((BoolExpr *) node)->args)
869+
{
870+
Node *newarg;
871+
872+
newarg = process_sublinks_mutator(lfirst(l),
873+
(void *) &locTopQual);
874+
if (and_clause(newarg))
875+
newargs = nconc(newargs, ((BoolExpr *) newarg)->args);
876+
else
877+
newargs = lappend(newargs, newarg);
878+
}
879+
return (Node *) make_andclause(newargs);
880+
}
881+
882+
/* otherwise not at qual top-level */
883+
locTopQual = false;
884+
885+
if (or_clause(node))
886+
{
887+
List *newargs = NIL;
888+
List *l;
889+
890+
foreach(l, ((BoolExpr *) node)->args)
891+
{
892+
Node *newarg;
893+
894+
newarg = process_sublinks_mutator(lfirst(l),
895+
(void *) &locTopQual);
896+
if (or_clause(newarg))
897+
newargs = nconc(newargs, ((BoolExpr *) newarg)->args);
898+
else
899+
newargs = lappend(newargs, newarg);
900+
}
901+
return (Node *) make_orclause(newargs);
902+
}
858903

859904
return expression_tree_mutator(node,
860905
process_sublinks_mutator,

0 commit comments

Comments
 (0)