From 38a7ace1082e8a668007b800f6df379c38a37747 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 31 Jul 2026 10:26:54 +0800 Subject: [PATCH] Only test for sublink pullup --- src/backend/optimizer/plan/subselect.c | 2 +- src/backend/optimizer/util/var.c | 49 ++++++++++++++++++++++++++ src/include/optimizer/optimizer.h | 1 + 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 6aa8971c95d..03a37421bce 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -1650,7 +1650,7 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, * On the other hand, the WHERE clause must contain some Vars of the * parent query, else it's not gonna be a join. */ - if (!contain_vars_of_level(whereClause, 1)) + if (!contain_vars_of_level_parent(whereClause, 1)) return NULL; /* diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 907a255c36f..7a20c6ca021 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -76,6 +76,7 @@ static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context); static bool pull_vars_walker(Node *node, pull_vars_context *context); static bool contain_var_clause_walker(Node *node, void *context); static bool contain_vars_of_level_walker(Node *node, int *sublevels_up); +static bool contain_vars_of_level_walker2(Node *node, int *sublevels_up); static bool contain_vars_returning_old_or_new_walker(Node *node, void *context); static bool locate_var_of_level_walker(Node *node, locate_var_of_level_context *context); @@ -492,7 +493,55 @@ contain_vars_of_level_walker(Node *node, int *sublevels_up) sublevels_up); } +bool +contain_vars_of_level_parent(Node *node, int levelsup) +{ + int sublevels_up = levelsup; + return query_or_expression_tree_walker(node, + contain_vars_of_level_walker2, + &sublevels_up, + 0); +} + +static bool +contain_vars_of_level_walker2(Node *node, int *sublevels_up) +{ + if (node == NULL) + return false; + if (IsA(node, Var)) + { + if (((Var *) node)->varlevelsup == *sublevels_up) + return true; /* abort tree traversal and return true */ + return false; + } + if (IsA(node, CurrentOfExpr)) + { + if (*sublevels_up == 0) + return true; + return false; + } + if (IsA(node, PlaceHolderVar)) + { + if (((PlaceHolderVar *) node)->phlevelsup == *sublevels_up) + return true; /* abort the tree traversal and return true */ + /* else fall through to check the contained expr */ + } + if (IsA(node, Query)) + { + /* Recurse into subselects */ + bool result; + + result = query_tree_walker((Query *) node, + contain_vars_of_level_walker2, + sublevels_up, + 0); + return result; + } + return expression_tree_walker(node, + contain_vars_of_level_walker2, + sublevels_up); +} /* * contain_vars_returning_old_or_new * Recursively scan a clause to discover whether it contains any Var nodes diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index cb6241e2bdd..cd17ffc92bf 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -209,6 +209,7 @@ extern void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos); extern List *pull_vars_of_level(Node *node, int levelsup); extern bool contain_var_clause(Node *node); extern bool contain_vars_of_level(Node *node, int levelsup); +extern bool contain_vars_of_level_parent(Node *node, int levelsup); extern bool contain_vars_returning_old_or_new(Node *node); extern int locate_var_of_level(Node *node, int levelsup); extern List *pull_var_clause(Node *node, int flags); -- 2.43.0