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

Lines changed: 14 additions & 9 deletions
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

Lines changed: 51 additions & 6 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy