From 119e61daa7bf79c229cad4ce286f6eb2cc14bbd0 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Mon, 25 Dec 2023 16:08:15 +0300 Subject: [PATCH 2/6] Handle ConvertRowtypeExprs in pull_vars_clause(). This is a preparatory patch to fix the unresolved ConvertRowtypeExpr references in the targetlists. The patch allows pull_vars_clause() to return ConvertRowtypeExprs without recursing into those. Because of the recent work to support indexes and triggers on partitioned table, every caller of pull_var_clause() can encounter a ConvertRowtype embedding a whole-row reference. Current behavior is unchanged. Callers which don't need to recurse to ConvertRowtypeExprs should explicitly pass PVC_INCLUDE_CONVERTROWTYPES. The patch is taken from /message-id/CAFjFpRc8ZoDm0%2Bzhx%2BMckwGyEqkOzWcpVqbvjaxwdGarZSNrmA%40mail.gmail.com --- src/backend/nodes/nodeFuncs.c | 32 ++++++++++++++++++++++++++++ src/backend/optimizer/plan/setrefs.c | 32 ---------------------------- src/backend/optimizer/util/var.c | 18 ++++++++++++++++ src/include/nodes/nodeFuncs.h | 1 + src/include/optimizer/optimizer.h | 2 ++ 5 files changed, 53 insertions(+), 32 deletions(-) diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 0d00e029f32..1ec4460e707 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -4807,3 +4807,35 @@ planstate_walk_members(PlanState **planstates, int nplans, return false; } + +/* + * is_converted_whole_row_reference + * If the given node is a ConvertRowtypeExpr encapsulating a whole-row + * reference as implicit cast (i.e a parent's whole row reference + * translated by adjust_appendrel_attrs()), return true. Otherwise return + * false. + */ +bool +is_converted_whole_row_reference(Node *node) +{ + ConvertRowtypeExpr *convexpr; + + if (!node || !IsA(node, ConvertRowtypeExpr)) + return false; + + /* Traverse nested ConvertRowtypeExpr's. */ + convexpr = castNode(ConvertRowtypeExpr, node); + while (convexpr->convertformat == COERCE_IMPLICIT_CAST && + IsA(convexpr->arg, ConvertRowtypeExpr)) + convexpr = castNode(ConvertRowtypeExpr, convexpr->arg); + + if (IsA(convexpr->arg, Var)) + { + Var *var = castNode(Var, convexpr->arg); + + if (var->varattno == 0) + return true; + } + + return false; +} diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index f7c79db7b2b..296644f8c2e 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -214,8 +214,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root, List *runcondition, Plan *plan); -static bool is_converted_whole_row_reference(Node *node); - /***************************************************************************** * * SUBPLAN REFERENCES @@ -3676,33 +3674,3 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context) return expression_tree_walker(node, extract_query_dependencies_walker, (void *) context); } - -/* - * is_converted_whole_row_reference - * If the given node is a ConvertRowtypeExpr encapsulating a whole-row - * reference as implicit cast, return true. Otherwise return false. - */ -static bool -is_converted_whole_row_reference(Node *node) -{ - ConvertRowtypeExpr *convexpr; - - if (!node || !IsA(node, ConvertRowtypeExpr)) - return false; - - /* Traverse nested ConvertRowtypeExpr's. */ - convexpr = castNode(ConvertRowtypeExpr, node); - while (convexpr->convertformat == COERCE_IMPLICIT_CAST && - IsA(convexpr->arg, ConvertRowtypeExpr)) - convexpr = castNode(ConvertRowtypeExpr, convexpr->arg); - - if (IsA(convexpr->arg, Var)) - { - Var *var = castNode(Var, convexpr->arg); - - if (var->varattno == 0) - return true; - } - - return false; -} diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index f7534ad53d6..4ca911591ec 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -594,6 +594,11 @@ locate_var_of_level_walker(Node *node, * Vars within a PHV's expression are included in the result only * when PVC_RECURSE_PLACEHOLDERS is specified. * + * ConvertRowtypeExprs encapsulating whole row references are handled + * according to these bits in 'flags': + * PVC_INCLUDE_CONVERTROWTYPES include ConvertRowtypeExprs in output list + * by default - recurse into ConvertRowtypeExprs arguments + * * GroupingFuncs are treated exactly like Aggrefs, and so do not need * their own flag bits. * @@ -707,6 +712,19 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context) else elog(ERROR, "PlaceHolderVar found where not expected"); } + else if (is_converted_whole_row_reference(node)) + { + if (context->flags & PVC_INCLUDE_CONVERTROWTYPES) + { + context->varlist = lappend(context->varlist, node); + /* we do NOT descend into the contained expression */ + return false; + } + else + { + /* fall through to recurse into the ConvertRowtype's argument. */ + } + } return expression_tree_walker(node, pull_var_clause_walker, (void *) context); } diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h index caefc39f6a2..d43e87e2402 100644 --- a/src/include/nodes/nodeFuncs.h +++ b/src/include/nodes/nodeFuncs.h @@ -221,4 +221,5 @@ extern bool planstate_tree_walker_impl(struct PlanState *planstate, planstate_tree_walker_callback walker, void *context); +extern bool is_converted_whole_row_reference(Node *node); #endif /* NODEFUNCS_H */ diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index 93e3dc719da..550e001dc05 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -191,6 +191,8 @@ extern SortGroupClause *get_sortgroupref_clause_noerr(Index sortref, * output list */ #define PVC_RECURSE_PLACEHOLDERS 0x0020 /* recurse into PlaceHolderVar * arguments */ +#define PVC_INCLUDE_CONVERTROWTYPES 0x0040 /* include ConvertRowtypeExprs in + * output list */ extern Bitmapset *pull_varnos(PlannerInfo *root, Node *node); extern Bitmapset *pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup); -- 2.34.1