From 205737bb97d097d1ac0a6b7c220c7e0234a50582 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
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 https://www.postgresql.org/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

