From 850767aa755f90ceedf48b504fadb49ddb562aa7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 5 Dec 2016 18:10:04 -0800
Subject: [PATCH 2/4] Make get_last_attnums more generic.

---
 src/backend/executor/execUtils.c | 48 +++++++++++++++++++++++++++++-----------
 src/include/executor/executor.h  |  4 ++++
 2 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 3d6a3801c0..d205101b89 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -47,7 +47,14 @@
 #include "utils/rel.h"
 
 
-static bool get_last_attnums(Node *node, ProjectionInfo *projInfo);
+typedef struct LastLastAttnumInfo
+{
+	AttrNumber last_outer;
+	AttrNumber last_inner;
+	AttrNumber last_scan;
+} LastAttnumInfo;
+
+
 static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
 
 
@@ -580,7 +587,10 @@ ExecBuildProjectionInfo(List *targetList,
 			/* Not a simple variable, add it to generic targetlist */
 			exprlist = lappend(exprlist, gstate);
 			/* Examine expr to include contained Vars in lastXXXVar counts */
-			get_last_attnums((Node *) variable, projInfo);
+			ExecGetLastAttnums((Node *) variable,
+							   &projInfo->pi_lastOuterVar,
+							   &projInfo->pi_lastInnerVar,
+							   &projInfo->pi_lastScanVar);
 		}
 	}
 	projInfo->pi_targetlist = exprlist;
@@ -591,13 +601,13 @@ ExecBuildProjectionInfo(List *targetList,
 }
 
 /*
- * get_last_attnums: expression walker for ExecBuildProjectionInfo
+ * get_last_attnums_walker: expression walker for ExecBuildProjectionInfo
  *
  *	Update the lastXXXVar counts to be at least as large as the largest
  *	attribute numbers found in the expression
  */
 static bool
-get_last_attnums(Node *node, ProjectionInfo *projInfo)
+get_last_attnums_walker(Node *node, LastAttnumInfo *info)
 {
 	if (node == NULL)
 		return false;
@@ -609,21 +619,17 @@ get_last_attnums(Node *node, ProjectionInfo *projInfo)
 		switch (variable->varno)
 		{
 			case INNER_VAR:
-				if (projInfo->pi_lastInnerVar < attnum)
-					projInfo->pi_lastInnerVar = attnum;
+				info->last_inner = Max(info->last_inner, attnum);
 				break;
 
 			case OUTER_VAR:
-				if (projInfo->pi_lastOuterVar < attnum)
-					projInfo->pi_lastOuterVar = attnum;
+				info->last_outer = Max(info->last_outer, attnum);
 				break;
 
 				/* INDEX_VAR is handled by default case */
 
 			default:
-				if (projInfo->pi_lastScanVar < attnum)
-					projInfo->pi_lastScanVar = attnum;
-				break;
+				info->last_scan = Max(info->last_scan, attnum);
 		}
 		return false;
 	}
@@ -640,10 +646,26 @@ get_last_attnums(Node *node, ProjectionInfo *projInfo)
 		return false;
 	if (IsA(node, GroupingFunc))
 		return false;
-	return expression_tree_walker(node, get_last_attnums,
-								  (void *) projInfo);
+	return expression_tree_walker(node, get_last_attnums_walker,
+								  (void *) info);
 }
 
+void
+ExecGetLastAttnums(Node *node, int *last_outer, int *last_inner,
+				   int *last_scan)
+{
+	LastAttnumInfo info = {0,0,0};
+
+	get_last_attnums_walker(node, &info);
+	if (last_outer && *last_outer < info.last_outer)
+		*last_outer = info.last_outer;
+	if (last_inner && *last_inner < info.last_inner)
+		*last_inner = info.last_inner;
+	if (last_scan && *last_scan < info.last_scan)
+		*last_scan = info.last_scan;
+}
+
+
 /* ----------------
  *		ExecAssignProjectionInfo
  *
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 02dbe7b228..32e1838e15 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -354,6 +354,10 @@ extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
 extern void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc);
 extern void ExecAssignResultTypeFromTL(PlanState *planstate);
 extern TupleDesc ExecGetResultType(PlanState *planstate);
+extern void ExecGetLastAttnums(Node *node,
+							   int *last_outer,
+							   int *last_inner,
+							   int *last_scan);
 extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList,
 						ExprContext *econtext,
 						TupleTableSlot *slot,
-- 
2.11.0.22.g8d7a455.dirty

