From 205737bb97d097d1ac0a6b7c220c7e0234a50582 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 d2e2af4f811..4ce0230aad5 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -4793,3 +4793,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 706643b1b88..09314fac672 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -213,8 +213,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root, List *runcondition, Plan *plan); -static bool is_converted_whole_row_reference(Node *node); - /***************************************************************************** * * SUBPLAN REFERENCES @@ -3652,33 +3650,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 844fc30978b..dfe869c3674 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -589,6 +589,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. * @@ -702,6 +707,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 eaba59bed83..8d30d6cbac5 100644 --- a/src/include/nodes/nodeFuncs.h +++ b/src/include/nodes/nodeFuncs.h @@ -219,4 +219,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 7b63c5cf718..4381124f6e8 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