aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/prep/prepjointree.c26
-rw-r--r--src/test/regress/expected/subselect.out12
-rw-r--r--src/test/regress/sql/subselect.sql9
3 files changed, 37 insertions, 10 deletions
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 5d163292c58..ac622a34d9d 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -246,6 +246,7 @@ pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
* as a sublink that is executed only for row pairs that meet the
* other join conditions. Fixing this seems to require considerable
* restructuring of the executor, but maybe someday it can happen.
+ * (See also the comparable case in pull_up_sublinks_qual_recurse.)
*
* We don't expect to see any pre-existing JOIN_SEMI or JOIN_ANTI
* nodes here.
@@ -331,9 +332,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
j->rarg = pull_up_sublinks_jointree_recurse(root,
j->rarg,
&child_rels);
- /* Pulled-up ANY/EXISTS quals can use those rels too */
- child_rels = bms_add_members(child_rels, available_rels);
- /* ... and any inserted joins get stacked onto j->rarg */
+ /* Any inserted joins get stacked onto j->rarg */
j->quals = pull_up_sublinks_qual_recurse(root,
j->quals,
child_rels,
@@ -355,9 +354,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
j->rarg = pull_up_sublinks_jointree_recurse(root,
j->rarg,
&child_rels);
- /* Pulled-up ANY/EXISTS quals can use those rels too */
- child_rels = bms_add_members(child_rels, available_rels);
- /* ... and any inserted joins get stacked onto j->rarg */
+ /* Any inserted joins get stacked onto j->rarg */
j->quals = pull_up_sublinks_qual_recurse(root,
j->quals,
child_rels,
@@ -377,7 +374,6 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
/* If the immediate argument of NOT is EXISTS, try to convert */
SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
JoinExpr *j;
- Relids child_rels;
if (sublink && IsA(sublink, SubLink))
{
@@ -387,17 +383,27 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
available_rels);
if (j)
{
+ /*
+ * For the moment, refrain from recursing underneath NOT.
+ * As in pull_up_sublinks_jointree_recurse, recursing here
+ * would result in inserting a join underneath an ANTI
+ * join with which it could not commute, and that could
+ * easily lead to a worse plan than what we've
+ * historically generated.
+ */
+#ifdef NOT_USED
/* Yes; recursively process what we pulled up */
+ Relids child_rels;
+
j->rarg = pull_up_sublinks_jointree_recurse(root,
j->rarg,
&child_rels);
- /* Pulled-up ANY/EXISTS quals can use those rels too */
- child_rels = bms_add_members(child_rels, available_rels);
- /* ... and any inserted joins get stacked onto j->rarg */
+ /* Any inserted joins get stacked onto j->rarg */
j->quals = pull_up_sublinks_qual_recurse(root,
j->quals,
child_rels,
&j->rarg);
+#endif
/* Now insert the new join node into the join tree */
j->larg = *jtlink;
*jtlink = (Node *) j;
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 2440dcd8225..8f180b9b19c 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -530,3 +530,15 @@ select '1'::text in (select '1'::name union all select '1'::name);
t
(1 row)
+--
+-- Test case for planner bug with nested EXISTS handling
+--
+select a.thousand from tenk1 a, tenk1 b
+where a.thousand = b.thousand
+ and exists ( select 1 from tenk1 c where b.hundred = c.hundred
+ and not exists ( select 1 from tenk1 d
+ where a.thousand = d.thousand ) );
+ thousand
+----------
+(0 rows)
+
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index 296e38b8c1e..0d117c878fa 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -341,3 +341,12 @@ from
--
select '1'::text in (select '1'::name union all select '1'::name);
+
+--
+-- Test case for planner bug with nested EXISTS handling
+--
+select a.thousand from tenk1 a, tenk1 b
+where a.thousand = b.thousand
+ and exists ( select 1 from tenk1 c where b.hundred = c.hundred
+ and not exists ( select 1 from tenk1 d
+ where a.thousand = d.thousand ) );