From e493597e84fb795f9aa0db07c8f24e08183187ab Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Thu, 16 Feb 2023 18:02:41 +0800 Subject: [PATCH v1] Fix variable-free clause distribution --- src/backend/optimizer/plan/initsplan.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index fe4c8c63c9..3edc38048d 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -64,6 +64,9 @@ typedef struct JoinTreeItem JoinDomain *jdomain; /* join domain for its ON/WHERE clauses */ struct JoinTreeItem *jti_parent; /* JoinTreeItem for this node's * parent, or NULL if it's the top */ + bool below_outer_join; /* true if this node is within the + * nullable side of a higher-level + * outer join */ Relids qualscope; /* base+OJ Relids syntactically included in * this jointree node */ Relids inner_join_rels; /* base+OJ Relids syntactically included @@ -84,6 +87,7 @@ typedef struct JoinTreeItem static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex); static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode, + bool below_outer_join, JoinDomain *parent_domain, JoinTreeItem *parent_jtitem, List **item_list); @@ -758,7 +762,7 @@ deconstruct_jointree(PlannerInfo *root) root->outer_join_rels = NULL; /* Perform the initial scan of the jointree */ - result = deconstruct_recurse(root, (Node *) root->parse->jointree, + result = deconstruct_recurse(root, (Node *) root->parse->jointree, false, top_jdomain, NULL, &item_list); @@ -813,7 +817,7 @@ deconstruct_jointree(PlannerInfo *root) * Return value is the appropriate joinlist for this jointree node. */ static List * -deconstruct_recurse(PlannerInfo *root, Node *jtnode, +deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, JoinDomain *parent_domain, JoinTreeItem *parent_jtitem, List **item_list) @@ -827,6 +831,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, jtitem = palloc0_object(JoinTreeItem); jtitem->jtnode = jtnode; jtitem->jti_parent = parent_jtitem; + jtitem->below_outer_join = below_outer_join; if (IsA(jtnode, RangeTblRef)) { @@ -871,6 +876,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, int sub_members; sub_joinlist = deconstruct_recurse(root, lfirst(l), + below_outer_join, parent_domain, jtitem, item_list); @@ -914,11 +920,13 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, jtitem->jdomain = parent_domain; /* Recurse */ leftjoinlist = deconstruct_recurse(root, j->larg, + below_outer_join, parent_domain, jtitem, item_list); left_item = (JoinTreeItem *) llast(*item_list); rightjoinlist = deconstruct_recurse(root, j->rarg, + below_outer_join, parent_domain, jtitem, item_list); @@ -941,11 +949,13 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, jtitem->jdomain = child_domain; /* Recurse */ leftjoinlist = deconstruct_recurse(root, j->larg, + below_outer_join, parent_domain, jtitem, item_list); left_item = (JoinTreeItem *) llast(*item_list); rightjoinlist = deconstruct_recurse(root, j->rarg, + true, child_domain, jtitem, item_list); @@ -980,11 +990,13 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, jtitem->jdomain = parent_domain; /* Recurse */ leftjoinlist = deconstruct_recurse(root, j->larg, + below_outer_join, parent_domain, jtitem, item_list); left_item = (JoinTreeItem *) llast(*item_list); rightjoinlist = deconstruct_recurse(root, j->rarg, + below_outer_join, parent_domain, jtitem, item_list); @@ -1011,6 +1023,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, child_domain->jd_relids = NULL; /* filled by recursion */ root->join_domains = lappend(root->join_domains, child_domain); leftjoinlist = deconstruct_recurse(root, j->larg, + true, child_domain, jtitem, item_list); @@ -1020,6 +1033,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, child_domain->jd_relids = NULL; /* filled by recursion */ root->join_domains = lappend(root->join_domains, child_domain); rightjoinlist = deconstruct_recurse(root, j->rarg, + true, child_domain, jtitem, item_list); @@ -2269,8 +2283,9 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, } else { - /* eval at join domain level */ - relids = bms_copy(jtitem->jdomain->jd_relids); + /* eval at join domain level if not below outer join */ + relids = jtitem->below_outer_join ? + bms_copy(qualscope) : bms_copy(jtitem->jdomain->jd_relids); /* mark as gating qual */ pseudoconstant = true; /* tell createplan.c to check for gating quals */ -- 2.31.0