aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/orclauses.c12
-rw-r--r--src/test/regress/expected/join.out27
-rw-r--r--src/test/regress/sql/join.sql4
3 files changed, 41 insertions, 2 deletions
diff --git a/src/backend/optimizer/util/orclauses.c b/src/backend/optimizer/util/orclauses.c
index 9e954d0d35f..8fecabbcda1 100644
--- a/src/backend/optimizer/util/orclauses.c
+++ b/src/backend/optimizer/util/orclauses.c
@@ -178,6 +178,7 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
{
Node *orarg = (Node *) lfirst(lc);
List *subclauses = NIL;
+ Node *subclause;
/* OR arguments should be ANDs or sub-RestrictInfos */
if (and_clause(orarg))
@@ -226,9 +227,16 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
/*
* OK, add subclause(s) to the result OR. If we found more than one,
- * we need an AND node.
+ * we need an AND node. But if we found only one, and it is itself an
+ * OR node, add its subclauses to the result instead; this is needed
+ * to preserve AND/OR flatness (ie, no OR directly underneath OR).
*/
- clauselist = lappend(clauselist, make_ands_explicit(subclauses));
+ subclause = (Node *) make_ands_explicit(subclauses);
+ if (or_clause(subclause))
+ clauselist = list_concat(clauselist,
+ list_copy(((BoolExpr *) subclause)->args));
+ else
+ clauselist = lappend(clauselist, subclause);
}
/*
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 1cb1c51a6ee..25011847a04 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2827,6 +2827,33 @@ select * from tenk1 a join tenk1 b on
Index Cond: (unique2 = 3)
(12 rows)
+explain (costs off)
+select * from tenk1 a join tenk1 b on
+ (a.unique1 = 1 and b.unique1 = 2) or
+ ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4);
+ QUERY PLAN
+----------------------------------------------------------------------------------------------------------------------
+ Nested Loop
+ Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4)))
+ -> Bitmap Heap Scan on tenk1 b
+ Recheck Cond: ((unique1 = 2) OR (hundred = 4))
+ -> BitmapOr
+ -> Bitmap Index Scan on tenk1_unique1
+ Index Cond: (unique1 = 2)
+ -> Bitmap Index Scan on tenk1_hundred
+ Index Cond: (hundred = 4)
+ -> Materialize
+ -> Bitmap Heap Scan on tenk1 a
+ Recheck Cond: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7))
+ -> BitmapOr
+ -> Bitmap Index Scan on tenk1_unique1
+ Index Cond: (unique1 = 1)
+ -> Bitmap Index Scan on tenk1_unique2
+ Index Cond: (unique2 = 3)
+ -> Bitmap Index Scan on tenk1_unique2
+ Index Cond: (unique2 = 7)
+(19 rows)
+
--
-- test placement of movable quals in a parameterized join tree
--
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index fa3e0686261..718e1d9fc38 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -774,6 +774,10 @@ select * from tenk1 a join tenk1 b on
explain (costs off)
select * from tenk1 a join tenk1 b on
(a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.ten = 4);
+explain (costs off)
+select * from tenk1 a join tenk1 b on
+ (a.unique1 = 1 and b.unique1 = 2) or
+ ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4);
--
-- test placement of movable quals in a parameterized join tree