aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/subselect.c5
-rw-r--r--src/backend/optimizer/prep/prepjointree.c41
2 files changed, 43 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 493bc86299f..45eaa03fda7 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1065,6 +1065,11 @@ SS_process_ctes(PlannerInfo *root)
* (Notionally, we replace the SubLink with a constant TRUE, then elide the
* redundant constant from the qual.)
*
+ * On success, the caller is also responsible for recursively applying
+ * pull_up_sublinks processing to the rarg and quals of the returned JoinExpr.
+ * (On failure, there is no need to do anything, since pull_up_sublinks will
+ * be applied when we recursively plan the sub-select.)
+ *
* Side effects of a successful conversion include adding the SubLink's
* subselect to the query's rangetable, so that it can be referenced in
* the JoinExpr's rarg.
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index a70439cc674..5d163292c58 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -318,6 +318,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
{
SubLink *sublink = (SubLink *) node;
JoinExpr *j;
+ Relids child_rels;
/* Is it a convertible ANY or EXISTS clause? */
if (sublink->subLinkType == ANY_SUBLINK)
@@ -326,7 +327,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
available_rels);
if (j)
{
- /* Yes, insert the new join node into the join tree */
+ /* Yes; recursively process what we pulled up */
+ 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 */
+ j->quals = pull_up_sublinks_qual_recurse(root,
+ j->quals,
+ child_rels,
+ &j->rarg);
+ /* Now insert the new join node into the join tree */
j->larg = *jtlink;
*jtlink = (Node *) j;
/* and return NULL representing constant TRUE */
@@ -339,7 +351,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
available_rels);
if (j)
{
- /* Yes, insert the new join node into the join tree */
+ /* Yes; recursively process what we pulled up */
+ 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 */
+ j->quals = pull_up_sublinks_qual_recurse(root,
+ j->quals,
+ child_rels,
+ &j->rarg);
+ /* Now insert the new join node into the join tree */
j->larg = *jtlink;
*jtlink = (Node *) j;
/* and return NULL representing constant TRUE */
@@ -354,6 +377,7 @@ 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))
{
@@ -363,7 +387,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
available_rels);
if (j)
{
- /* Yes, insert the new join node into the join tree */
+ /* Yes; recursively process what we pulled up */
+ 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 */
+ j->quals = pull_up_sublinks_qual_recurse(root,
+ j->quals,
+ child_rels,
+ &j->rarg);
+ /* Now insert the new join node into the join tree */
j->larg = *jtlink;
*jtlink = (Node *) j;
/* and return NULL representing constant TRUE */