From d32280c641935bf84f6725a66947f7207043b4d0 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@enterprisedb.com>
Date: Sat, 12 Jan 2019 15:36:57 +1300
Subject: [PATCH 3/5] Convert type of various relationOids members List ->
 oid_vector.

---
 src/backend/commands/copy.c          |  2 +-
 src/backend/executor/execParallel.c  |  2 +-
 src/backend/nodes/copyfuncs.c        |  6 +++++-
 src/backend/nodes/outfuncs.c         | 14 +++++++++++--
 src/backend/nodes/readfuncs.c        | 31 +++++++++++++++++++++++++++-
 src/backend/optimizer/plan/planner.c |  8 +++----
 src/backend/optimizer/plan/setrefs.c | 23 ++++++++++-----------
 src/backend/utils/cache/plancache.c  | 24 ++++++++++-----------
 src/include/nodes/plannodes.h        |  3 ++-
 src/include/nodes/relation.h         |  3 ++-
 src/include/optimizer/planmain.h     |  2 +-
 src/include/optimizer/planner.h      |  2 +-
 src/include/utils/builtins.h         | 10 +++++++++
 src/include/utils/plancache.h        |  5 +++--
 14 files changed, 95 insertions(+), 40 deletions(-)

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index a61a628471..fd024748e5 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -1533,7 +1533,7 @@ BeginCopy(ParseState *pstate,
 			 * make any guarantees of that in the planner, so check the whole
 			 * list and make sure we find the original relation.
 			 */
-			if (!list_member_oid(plan->relationOids, queryRelId))
+			if (!oid_vector_find(&plan->relationOids, &queryRelId))
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 						 errmsg("relation referenced by COPY statement has changed")));
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index d6cfd28ddc..8cf974f609 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -203,7 +203,7 @@ ExecSerializePlan(Plan *plan, EState *estate)
 
 	pstmt->rewindPlanIDs = NULL;
 	pstmt->rowMarks = NIL;
-	pstmt->relationOids = NIL;
+	oid_vector_init(&pstmt->relationOids);
 	pstmt->invalItems = NIL;	/* workers can't replan anyway... */
 	pstmt->paramExecTypes = estate->es_plannedstmt->paramExecTypes;
 	pstmt->utilityStmt = NULL;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 006a3d1772..4014d2627d 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -61,6 +61,10 @@
 		memcpy(newnode->fldname, from->fldname, _size); \
 	} while (0)
 
+/* Copy a field that is an oid_vector */
+#define COPY_OID_VECTOR_FIELD(fldname) \
+	oid_vector_assign(&newnode->fldname, &from->fldname)
+
 /* Copy a parse location field (for Copy, this is same as scalar case) */
 #define COPY_LOCATION_FIELD(fldname) \
 	(newnode->fldname = from->fldname)
@@ -95,7 +99,7 @@ _copyPlannedStmt(const PlannedStmt *from)
 	COPY_NODE_FIELD(subplans);
 	COPY_BITMAPSET_FIELD(rewindPlanIDs);
 	COPY_NODE_FIELD(rowMarks);
-	COPY_NODE_FIELD(relationOids);
+	COPY_OID_VECTOR_FIELD(relationOids);
 	COPY_NODE_FIELD(invalItems);
 	COPY_NODE_FIELD(paramExecTypes);
 	COPY_NODE_FIELD(utilityStmt);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 0fde876c77..ba6841138a 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -138,6 +138,16 @@ static void outChar(StringInfo str, char c);
 			appendStringInfo(str, " %s", booltostr(node->fldname[i])); \
 	} while(0)
 
+#define WRITE_OID_VECTOR_FIELD(fldname) \
+	do { \
+		int len = oid_vector_size(&node->fldname); \
+		const Oid *data = oid_vector_cbegin(&node->fldname); \
+		appendStringInfoString(str, " :" CppAsString(fldname) " "); \
+		appendStringInfo(str, " %d", len); \
+		for (int i = 0; i < len; i++) \
+			appendStringInfo(str, " %u", data[i]); \
+	} while(0)
+
 
 #define booltostr(x)  ((x) ? "true" : "false")
 
@@ -313,7 +323,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node)
 	WRITE_NODE_FIELD(subplans);
 	WRITE_BITMAPSET_FIELD(rewindPlanIDs);
 	WRITE_NODE_FIELD(rowMarks);
-	WRITE_NODE_FIELD(relationOids);
+	WRITE_OID_VECTOR_FIELD(relationOids);
 	WRITE_NODE_FIELD(invalItems);
 	WRITE_NODE_FIELD(paramExecTypes);
 	WRITE_NODE_FIELD(utilityStmt);
@@ -2158,7 +2168,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node)
 	WRITE_NODE_FIELD(finalrowmarks);
 	WRITE_NODE_FIELD(resultRelations);
 	WRITE_NODE_FIELD(rootResultRelations);
-	WRITE_NODE_FIELD(relationOids);
+	WRITE_OID_VECTOR_FIELD(relationOids);
 	WRITE_NODE_FIELD(invalItems);
 	WRITE_NODE_FIELD(paramExecTypes);
 	WRITE_UINT_FIELD(lastPHId);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index ec6f2569ab..63bc3028da 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -171,6 +171,11 @@
 	token = pg_strtok(&length);		/* skip :fldname */ \
 	local_node->fldname = readBoolCols(len);
 
+/* Read an oid vector */
+#define READ_OID_VECTOR_FIELD(fldname) \
+	token = pg_strtok(&length);		/* skip :fldname */ \
+	readOidVector(&local_node->fldname);
+
 /* Routine exit */
 #define READ_DONE() \
 	return local_node
@@ -1509,7 +1514,7 @@ _readPlannedStmt(void)
 	READ_NODE_FIELD(subplans);
 	READ_BITMAPSET_FIELD(rewindPlanIDs);
 	READ_NODE_FIELD(rowMarks);
-	READ_NODE_FIELD(relationOids);
+	READ_OID_VECTOR_FIELD(relationOids);
 	READ_NODE_FIELD(invalItems);
 	READ_NODE_FIELD(paramExecTypes);
 	READ_NODE_FIELD(utilityStmt);
@@ -2960,3 +2965,27 @@ readBoolCols(int numCols)
 
 	return bool_vals;
 }
+
+/*
+ * readOidVector
+ */
+void
+readOidVector(oid_vector *vec)
+{
+	int			tokenLength,
+				len,
+				i;
+	const char *token;
+	Oid			val;
+
+	token = pg_strtok(&tokenLength);
+	len = atoi(token);
+
+	oid_vector_reset(vec);
+	for (i = 0; i < len; i++)
+	{
+		token = pg_strtok(&tokenLength);
+		val = atooid(token);
+		oid_vector_append(vec, &val);
+	}
+}
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index b849ae03b8..562bacaa13 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -307,7 +307,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	glob->finalrowmarks = NIL;
 	glob->resultRelations = NIL;
 	glob->rootResultRelations = NIL;
-	glob->relationOids = NIL;
+	oid_vector_init(&glob->relationOids);
 	glob->invalItems = NIL;
 	glob->paramExecTypes = NIL;
 	glob->lastPHId = 0;
@@ -5966,7 +5966,7 @@ expression_planner(Expr *expr)
  */
 Expr *
 expression_planner_with_deps(Expr *expr,
-							 List **relationOids,
+							 oid_vector *relationOids,
 							 List **invalItems)
 {
 	Node	   *result;
@@ -5976,7 +5976,7 @@ expression_planner_with_deps(Expr *expr,
 	/* Make up dummy planner state so we can use setrefs machinery */
 	MemSet(&glob, 0, sizeof(glob));
 	glob.type = T_PlannerGlobal;
-	glob.relationOids = NIL;
+	oid_vector_init(&glob.relationOids);
 	glob.invalItems = NIL;
 
 	MemSet(&root, 0, sizeof(root));
@@ -5999,7 +5999,7 @@ expression_planner_with_deps(Expr *expr,
 	 */
 	(void) extract_query_dependencies_walker(result, &root);
 
-	*relationOids = glob.relationOids;
+	oid_vector_assign(relationOids, &glob.relationOids);
 	*invalItems = glob.invalItems;
 
 	return (Expr *) result;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 5d363edab8..01344ba456 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -424,7 +424,7 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
 	 * but it would probably cost more cycles than it would save.
 	 */
 	if (newrte->rtekind == RTE_RELATION)
-		glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
+		oid_vector_append(&glob->relationOids, &newrte->relid);
 }
 
 /*
@@ -1417,9 +1417,11 @@ fix_expr_common(PlannerInfo *root, Node *node)
 
 		/* Check for regclass reference */
 		if (ISREGCLASSCONST(con))
-			root->glob->relationOids =
-				lappend_oid(root->glob->relationOids,
-							DatumGetObjectId(con->constvalue));
+		{
+			Oid oid = DatumGetObjectId(con->constvalue);
+
+			oid_vector_append(&root->glob->relationOids, &oid);
+		}
 	}
 	else if (IsA(node, GroupingFunc))
 	{
@@ -2631,7 +2633,7 @@ record_plan_type_dependency(PlannerInfo *root, Oid typid)
  */
 void
 extract_query_dependencies(Node *query,
-						   List **relationOids,
+						   oid_vector *relationOids,
 						   List **invalItems,
 						   bool *hasRowSecurity)
 {
@@ -2641,7 +2643,7 @@ extract_query_dependencies(Node *query,
 	/* Make up dummy planner state so we can use this module's machinery */
 	MemSet(&glob, 0, sizeof(glob));
 	glob.type = T_PlannerGlobal;
-	glob.relationOids = NIL;
+	oid_vector_init(&glob.relationOids);
 	glob.invalItems = NIL;
 	/* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
 	glob.dependsOnRole = false;
@@ -2652,7 +2654,7 @@ extract_query_dependencies(Node *query,
 
 	(void) extract_query_dependencies_walker(query, &root);
 
-	*relationOids = glob.relationOids;
+	oid_vector_assign(relationOids, &glob.relationOids);
 	*invalItems = glob.invalItems;
 	*hasRowSecurity = glob.dependsOnRole;
 }
@@ -2697,13 +2699,10 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
 			RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
 
 			if (rte->rtekind == RTE_RELATION)
-				context->glob->relationOids =
-					lappend_oid(context->glob->relationOids, rte->relid);
+				oid_vector_append(&context->glob->relationOids, &rte->relid);
 			else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
 					 OidIsValid(rte->relid))
-				context->glob->relationOids =
-					lappend_oid(context->glob->relationOids,
-								rte->relid);
+				oid_vector_append(&context->glob->relationOids, &rte->relid);
 		}
 
 		/* And recurse into the query's subexpressions */
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 3f46b5dfb2..0ec33dcf30 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -206,7 +206,7 @@ CreateCachedPlan(RawStmt *raw_parse_tree,
 	plansource->resultDesc = NULL;
 	plansource->context = source_context;
 	plansource->query_list = NIL;
-	plansource->relationOids = NIL;
+	oid_vector_init(&plansource->relationOids);
 	plansource->invalItems = NIL;
 	plansource->search_path = NULL;
 	plansource->query_context = NULL;
@@ -273,7 +273,7 @@ CreateOneShotCachedPlan(RawStmt *raw_parse_tree,
 	plansource->resultDesc = NULL;
 	plansource->context = CurrentMemoryContext;
 	plansource->query_list = NIL;
-	plansource->relationOids = NIL;
+	oid_vector_init(&plansource->relationOids);
 	plansource->invalItems = NIL;
 	plansource->search_path = NULL;
 	plansource->query_context = NULL;
@@ -633,7 +633,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource,
 	 */
 	plansource->is_valid = false;
 	plansource->query_list = NIL;
-	plansource->relationOids = NIL;
+	oid_vector_reset(&plansource->relationOids);
 	plansource->invalItems = NIL;
 	plansource->search_path = NULL;
 
@@ -1379,7 +1379,7 @@ CopyCachedPlan(CachedPlanSource *plansource)
 											  ALLOCSET_START_SMALL_SIZES);
 	MemoryContextSwitchTo(querytree_context);
 	newsource->query_list = copyObject(plansource->query_list);
-	newsource->relationOids = copyObject(plansource->relationOids);
+	oid_vector_assign(&newsource->relationOids, &plansource->relationOids);
 	newsource->invalItems = copyObject(plansource->invalItems);
 	if (plansource->search_path)
 		newsource->search_path = CopyOverrideSearchPath(plansource->search_path);
@@ -1468,7 +1468,7 @@ CachedExpression *
 GetCachedExpression(Node *expr)
 {
 	CachedExpression *cexpr;
-	List	   *relationOids;
+	oid_vector	relationOids;
 	List	   *invalItems;
 	MemoryContext cexpr_context;
 	MemoryContext oldcxt;
@@ -1497,7 +1497,7 @@ GetCachedExpression(Node *expr)
 	cexpr->magic = CACHEDEXPR_MAGIC;
 	cexpr->expr = copyObject(expr);
 	cexpr->is_valid = true;
-	cexpr->relationOids = copyObject(relationOids);
+	oid_vector_assign(&cexpr->relationOids, &relationOids);
 	cexpr->invalItems = copyObject(invalItems);
 	cexpr->context = cexpr_context;
 
@@ -1786,8 +1786,8 @@ PlanCacheRelCallback(Datum arg, Oid relid)
 		/*
 		 * Check the dependency list for the rewritten querytree.
 		 */
-		if ((relid == InvalidOid) ? plansource->relationOids != NIL :
-			list_member_oid(plansource->relationOids, relid))
+		if ((relid == InvalidOid) ? !oid_vector_empty(&plansource->relationOids) :
+			oid_vector_find(&plansource->relationOids, &relid) != NULL)
 		{
 			/* Invalidate the querytree and generic plan */
 			plansource->is_valid = false;
@@ -1809,8 +1809,8 @@ PlanCacheRelCallback(Datum arg, Oid relid)
 
 				if (plannedstmt->commandType == CMD_UTILITY)
 					continue;	/* Ignore utility statements */
-				if ((relid == InvalidOid) ? plannedstmt->relationOids != NIL :
-					list_member_oid(plannedstmt->relationOids, relid))
+				if ((relid == InvalidOid) ? !oid_vector_empty(&plannedstmt->relationOids) :
+					oid_vector_find(&plannedstmt->relationOids, &relid) != NULL)
 				{
 					/* Invalidate the generic plan only */
 					plansource->gplan->is_valid = false;
@@ -1832,8 +1832,8 @@ PlanCacheRelCallback(Datum arg, Oid relid)
 		if (!cexpr->is_valid)
 			continue;
 
-		if ((relid == InvalidOid) ? cexpr->relationOids != NIL :
-			list_member_oid(cexpr->relationOids, relid))
+		if ((relid == InvalidOid) ? !oid_vector_empty(&cexpr->relationOids) :
+			oid_vector_find(&cexpr->relationOids, &relid) != NULL)
 		{
 			cexpr->is_valid = false;
 		}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 6d087c268f..006f980799 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
 #include "nodes/bitmapset.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
+#include "utils/builtins.h"
 
 
 /* ----------------------------------------------------------------
@@ -81,7 +82,7 @@ typedef struct PlannedStmt
 
 	List	   *rowMarks;		/* a list of PlanRowMark's */
 
-	List	   *relationOids;	/* OIDs of relations the plan depends on */
+	oid_vector	relationOids;	/* OIDs of relations the plan depends on */
 
 	List	   *invalItems;		/* other dependencies, as PlanInvalItems */
 
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 3430061361..9ccc5c7013 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -20,6 +20,7 @@
 #include "nodes/params.h"
 #include "nodes/parsenodes.h"
 #include "storage/block.h"
+#include "utils/builtins.h"
 
 
 /*
@@ -123,7 +124,7 @@ typedef struct PlannerGlobal
 
 	List	   *rootResultRelations;	/* "flat" list of integer RT indexes */
 
-	List	   *relationOids;	/* OIDs of relations the plan depends on */
+	oid_vector	relationOids;	/* OIDs of relations the plan depends on */
 
 	List	   *invalItems;		/* other dependencies, as PlanInvalItems */
 
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index bec0c38617..031035a3ce 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -120,7 +120,7 @@ extern Plan *set_plan_references(PlannerInfo *root, Plan *plan);
 extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid);
 extern void record_plan_type_dependency(PlannerInfo *root, Oid typid);
 extern void extract_query_dependencies(Node *query,
-						   List **relationOids,
+						   oid_vector *relationOids,
 						   List **invalItems,
 						   bool *hasRowSecurity);
 extern bool extract_query_dependencies_walker(Node *node, PlannerInfo *root);
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
index 8616681e0a..8418ed66df 100644
--- a/src/include/optimizer/planner.h
+++ b/src/include/optimizer/planner.h
@@ -56,7 +56,7 @@ extern Path *get_cheapest_fractional_path(RelOptInfo *rel,
 
 extern Expr *expression_planner(Expr *expr);
 extern Expr *expression_planner_with_deps(Expr *expr,
-							 List **relationOids,
+							 oid_vector *relationOids,
 							 List **invalItems);
 
 extern Expr *preprocess_phv_expression(PlannerInfo *root, Expr *expr);
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 03d0ee2766..2a8b8b808e 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -18,6 +18,13 @@
 #include "nodes/nodes.h"
 #include "utils/fmgrprotos.h"
 
+#define SV_PREFIX oid_vector
+#define SV_ELEMENT_TYPE Oid
+#define SV_SCOPE static inline
+#define SV_EQ(a, b) ((*a) == (*b))
+#define SV_DECLARE
+#define SV_DEFINE
+#include "lib/simplevector.h"
 
 /* bool.c */
 extern bool parse_bool(const char *value, bool *result);
@@ -57,6 +64,9 @@ extern oidvector *buildoidvector(const Oid *oids, int n);
 extern Oid	oidparse(Node *node);
 extern int	oid_cmp(const void *p1, const void *p2);
 
+/* readfuncs.c */
+extern void readOidVector(oid_vector *vec);
+
 /* regexp.c */
 extern char *regexp_fixed_prefix(text *text_re, bool case_insensitive,
 					Oid collation, bool *exact);
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 936fe6bef5..47b3d20285 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -18,6 +18,7 @@
 #include "access/tupdesc.h"
 #include "lib/ilist.h"
 #include "nodes/params.h"
+#include "utils/builtins.h"
 #include "utils/queryenvironment.h"
 
 /* Forward declaration, to avoid including parsenodes.h here */
@@ -106,7 +107,7 @@ typedef struct CachedPlanSource
 	MemoryContext context;		/* memory context holding all above */
 	/* These fields describe the current analyzed-and-rewritten query tree: */
 	List	   *query_list;		/* list of Query nodes, or NIL if not valid */
-	List	   *relationOids;	/* OIDs of relations the queries depend on */
+	oid_vector	relationOids;	/* OIDs of relations the queries depend on */
 	List	   *invalItems;		/* other dependencies, as PlanInvalItems */
 	struct OverrideSearchPath *search_path; /* search_path used for parsing
 											 * and planning */
@@ -174,7 +175,7 @@ typedef struct CachedExpression
 	Node	   *expr;			/* planned form of expression */
 	bool		is_valid;		/* is the expression still valid? */
 	/* remaining fields should be treated as private to plancache.c: */
-	List	   *relationOids;	/* OIDs of relations the expr depends on */
+	oid_vector	relationOids;	/* OIDs of relations the expr depends on */
 	List	   *invalItems;		/* other dependencies, as PlanInvalItems */
 	MemoryContext context;		/* context containing this CachedExpression */
 	dlist_node	node;			/* link in global list of CachedExpressions */
-- 
2.20.1

