This is an automated email from the ASF dual-hosted git repository.

chenjinbao1989 pushed a commit to branch cbdb-postgres-merge
in repository https://gitbox.apache.org/repos/asf/cloudberry.git


The following commit(s) were added to refs/heads/cbdb-postgres-merge by this 
push:
     new 2d4feaf4a2b Bring update_placeholder_eval_levels back
2d4feaf4a2b is described below

commit 2d4feaf4a2ba764ad43d3679b3902dc590012d89
Author: Jinbao Chen <[email protected]>
AuthorDate: Sat Nov 22 22:09:33 2025 +0800

    Bring update_placeholder_eval_levels back
---
 src/backend/optimizer/plan/initsplan.c   |  5 +-
 src/backend/optimizer/util/placeholder.c | 94 ++++++++++++++++++++++++++++++++
 src/include/optimizer/placeholder.h      |  1 +
 3 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/src/backend/optimizer/plan/initsplan.c 
b/src/backend/optimizer/plan/initsplan.c
index 8b29d23a032..b65897043ca 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -1216,7 +1216,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode,
                                /* Compute qualscope etc */
                                jtitem->qualscope = 
bms_union(left_item->qualscope,
                                                                                
          right_item->qualscope);
-                               jtitem->inner_join_rels = jtitem->qualscope;
+                               jtitem->inner_join_rels = 
bms_copy(jtitem->qualscope);
                                jtitem->left_rels = left_item->qualscope;
                                jtitem->right_rels = right_item->qualscope;
                                /* Inner join adds no restrictions for quals */
@@ -1531,7 +1531,10 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem 
*jtitem)
 
                /* And add the SpecialJoinInfo to join_info_list */
                if (sjinfo)
+               {
                        root->join_info_list = lappend(root->join_info_list, 
sjinfo);
+                       update_placeholder_eval_levels(root, sjinfo);
+               }
        }
        else
        {
diff --git a/src/backend/optimizer/util/placeholder.c 
b/src/backend/optimizer/util/placeholder.c
index 200ae30edb8..2282632d1cc 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -281,6 +281,100 @@ find_placeholders_in_expr(PlannerInfo *root, Node *expr)
        list_free(vars);
 }
 
+/*
+ * update_placeholder_eval_levels
+ *             Adjust the target evaluation levels for placeholders
+ *
+ * The initial eval_at level set by find_placeholder_info was the set of
+ * rels used in the placeholder's expression (or the whole subselect below
+ * the placeholder's syntactic location, if the expr is variable-free).
+ * If the query contains any outer joins that can null any of those rels,
+ * we must delay evaluation to above those joins.
+ *
+ * We repeat this operation each time we add another outer join to
+ * root->join_info_list.  It's somewhat annoying to have to do that, but
+ * since we don't have very much information on the placeholders' locations,
+ * it's hard to avoid.  Each placeholder's eval_at level must be correct
+ * by the time it starts to figure in outer-join delay decisions for higher
+ * outer joins.
+ *
+ * In future we might want to put additional policy/heuristics here to
+ * try to determine an optimal evaluation level.  The current rules will
+ * result in evaluation at the lowest possible level.  However, pushing a
+ * placeholder eval up the tree is likely to further constrain evaluation
+ * order for outer joins, so it could easily be counterproductive; and we
+ * don't have enough information at this point to make an intelligent choice.
+ */
+void
+update_placeholder_eval_levels(PlannerInfo *root, SpecialJoinInfo *new_sjinfo)
+{
+       ListCell   *lc1;
+
+       foreach(lc1, root->placeholder_list)
+       {
+               PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1);
+               Relids          syn_level = phinfo->ph_var->phrels;
+               Relids          eval_at;
+               bool            found_some;
+               ListCell   *lc2;
+
+               /*
+                * We don't need to do any work on this placeholder unless the
+                * newly-added outer join is syntactically beneath its location.
+                */
+               if (!bms_is_subset(new_sjinfo->syn_lefthand, syn_level) ||
+                       !bms_is_subset(new_sjinfo->syn_righthand, syn_level))
+                       continue;
+
+               /*
+                * Check for delays due to lower outer joins.  This is the same 
logic
+                * as in check_outerjoin_delay in initsplan.c, except that we 
don't
+                * have anything to do with the delay_upper_joins flags; delay 
of
+                * upper outer joins will be handled later, based on the eval_at
+                * values we compute now.
+                */
+               eval_at = phinfo->ph_eval_at;
+
+               do
+               {
+                       found_some = false;
+                       foreach(lc2, root->join_info_list)
+                       {
+                               SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) 
lfirst(lc2);
+
+                               /* disregard joins not within the PHV's 
sub-select */
+                               if (!bms_is_subset(sjinfo->syn_lefthand, 
syn_level) ||
+                                       !bms_is_subset(sjinfo->syn_righthand, 
syn_level))
+                                       continue;
+
+                               /* do we reference any nullable rels of this 
OJ? */
+                               if (bms_overlap(eval_at, sjinfo->min_righthand) 
||
+                                       (sjinfo->jointype == JOIN_FULL &&
+                                        bms_overlap(eval_at, 
sjinfo->min_lefthand)))
+                               {
+                                       /* yes; have we included all its rels 
in eval_at? */
+                                       if 
(!bms_is_subset(sjinfo->min_lefthand, eval_at) ||
+                                               
!bms_is_subset(sjinfo->min_righthand, eval_at))
+                                       {
+                                               /* no, so add them in */
+                                               eval_at = 
bms_add_members(eval_at,
+                                                                               
                  sjinfo->min_lefthand);
+                                               eval_at = 
bms_add_members(eval_at,
+                                                                               
                  sjinfo->min_righthand);
+                                               /* we'll need another iteration 
*/
+                                               found_some = true;
+                                       }
+                               }
+                       }
+               } while (found_some);
+
+               /* Can't move the PHV's eval_at level to above its syntactic 
level */
+               Assert(bms_is_subset(eval_at, syn_level));
+
+               phinfo->ph_eval_at = eval_at;
+       }
+}
+
 /*
  * fix_placeholder_input_needed_levels
  *             Adjust the "needed at" levels for placeholder inputs
diff --git a/src/include/optimizer/placeholder.h 
b/src/include/optimizer/placeholder.h
index 6653ac3fdc9..86c2b9151e6 100644
--- a/src/include/optimizer/placeholder.h
+++ b/src/include/optimizer/placeholder.h
@@ -32,5 +32,6 @@ extern bool contain_placeholder_references_to(PlannerInfo 
*root, Node *clause,
                                                                                
          int relid);
 
 extern void make_placeholders_for_subplans(PlannerInfo *root);
+extern void update_placeholder_eval_levels(PlannerInfo *root, SpecialJoinInfo 
*new_sjinfo);
 
 #endif                                                 /* PLACEHOLDER_H */


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to