From a7ae1dcf4939cf643c5abe8dd673e4b87a6efd42 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 25 Aug 2014 22:19:05 -0400
Subject: [PATCH] pg_upgrade:  prevent automatic oid assignment

Prevent automatic oid assignment when in binary upgrade mode.  Also
throw an error when contrib/pg_upgrade_support functions are called when
not in binary upgrade mode.

This prevent automatically-assigned oids from conflicting with later
pre-assigned oids coming from the old cluster.  It also makes sure oids
are preserved in call important cases.
---
 contrib/pg_upgrade_support/pg_upgrade_support.c | 17 +++++++++++++++++
 src/backend/catalog/heap.c                      | 12 +++++++-----
 src/backend/catalog/index.c                     | 13 +++++++------
 src/backend/catalog/pg_enum.c                   |  7 ++++++-
 src/backend/catalog/pg_type.c                   | 16 +++++++++++++---
 src/backend/catalog/toasting.c                  |  6 +++++-
 src/backend/commands/typecmds.c                 |  9 +++++++--
 src/backend/commands/user.c                     |  9 +++++++--
 8 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/contrib/pg_upgrade_support/pg_upgrade_support.c b/contrib/pg_upgrade_support/pg_upgrade_support.c
index edd41d06ae4..beaee7611df 100644
--- a/contrib/pg_upgrade_support/pg_upgrade_support.c
+++ b/contrib/pg_upgrade_support/pg_upgrade_support.c
@@ -38,12 +38,20 @@ PG_FUNCTION_INFO_V1(set_next_pg_authid_oid);
 
 PG_FUNCTION_INFO_V1(create_empty_extension);
 
+#define CHECK_IS_BINARY_UPGRADE 								\
+do { 															\
+	if (!IsBinaryUpgrade)										\
+		ereport(ERROR,											\
+				(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),	\
+				 (errmsg("function can only be called when server is in binary upgrade mode")))); \
+} while (0)
 
 Datum
 set_next_pg_type_oid(PG_FUNCTION_ARGS)
 {
 	Oid			typoid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_pg_type_oid = typoid;
 
 	PG_RETURN_VOID();
@@ -54,6 +62,7 @@ set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
 {
 	Oid			typoid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_array_pg_type_oid = typoid;
 
 	PG_RETURN_VOID();
@@ -64,6 +73,7 @@ set_next_toast_pg_type_oid(PG_FUNCTION_ARGS)
 {
 	Oid			typoid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_toast_pg_type_oid = typoid;
 
 	PG_RETURN_VOID();
@@ -74,6 +84,7 @@ set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
 {
 	Oid			reloid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_heap_pg_class_oid = reloid;
 
 	PG_RETURN_VOID();
@@ -84,6 +95,7 @@ set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
 {
 	Oid			reloid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_index_pg_class_oid = reloid;
 
 	PG_RETURN_VOID();
@@ -94,6 +106,7 @@ set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
 {
 	Oid			reloid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_toast_pg_class_oid = reloid;
 
 	PG_RETURN_VOID();
@@ -104,6 +117,7 @@ set_next_pg_enum_oid(PG_FUNCTION_ARGS)
 {
 	Oid			enumoid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_pg_enum_oid = enumoid;
 
 	PG_RETURN_VOID();
@@ -114,6 +128,7 @@ set_next_pg_authid_oid(PG_FUNCTION_ARGS)
 {
 	Oid			authoid = PG_GETARG_OID(0);
 
+	CHECK_IS_BINARY_UPGRADE;
 	binary_upgrade_next_pg_authid_oid = authoid;
 	PG_RETURN_VOID();
 }
@@ -129,6 +144,8 @@ create_empty_extension(PG_FUNCTION_ARGS)
 	Datum		extCondition;
 	List	   *requiredExtensions;
 
+	CHECK_IS_BINARY_UPGRADE;
+
 	if (PG_ARGISNULL(4))
 		extConfig = PointerGetDatum(NULL);
 	else
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 33eef9f1caf..c346edac93b 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1088,19 +1088,21 @@ heap_create_with_catalog(const char *relname,
 	 */
 	if (!OidIsValid(relid))
 	{
-		/*
-		 * Use binary-upgrade override for pg_class.oid/relfilenode, if
-		 * supplied.
-		 */
+		 /* Use binary-upgrade override for pg_class.oid/relfilenode? */
 		if (IsBinaryUpgrade &&
-			OidIsValid(binary_upgrade_next_heap_pg_class_oid) &&
 			(relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
 			 relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
 			 relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE))
 		{
+			if (!OidIsValid(binary_upgrade_next_heap_pg_class_oid))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("pg_class heap OID value not set when in binary upgrade mode")));
+
 			relid = binary_upgrade_next_heap_pg_class_oid;
 			binary_upgrade_next_heap_pg_class_oid = InvalidOid;
 		}
+		/* There might be no TOAST table, so we have to test for it. */
 		else if (IsBinaryUpgrade &&
 				 OidIsValid(binary_upgrade_next_toast_pg_class_oid) &&
 				 relkind == RELKIND_TOASTVALUE)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index a5a204eb40b..ee105940be0 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -796,13 +796,14 @@ index_create(Relation heapRelation,
 	 */
 	if (!OidIsValid(indexRelationId))
 	{
-		/*
-		 * Use binary-upgrade override for pg_class.oid/relfilenode, if
-		 * supplied.
-		 */
-		if (IsBinaryUpgrade &&
-			OidIsValid(binary_upgrade_next_index_pg_class_oid))
+		/* Use binary-upgrade override for pg_class.oid/relfilenode? */
+		if (IsBinaryUpgrade)
 		{
+			if (!OidIsValid(binary_upgrade_next_index_pg_class_oid))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("pg_class index OID value not set when in binary upgrade mode")));
+
 			indexRelationId = binary_upgrade_next_index_pg_class_oid;
 			binary_upgrade_next_index_pg_class_oid = InvalidOid;
 		}
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index b4f2051749d..086e80efcfb 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -341,8 +341,13 @@ restart:
 	}
 
 	/* Get a new OID for the new label */
-	if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_enum_oid))
+	if (IsBinaryUpgrade)
 	{
+		if (!OidIsValid(binary_upgrade_next_pg_enum_oid))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("pg_enum OID value not set when in binary upgrade mode")));
+
 		/*
 		 * Use binary-upgrade override for pg_enum.oid, if supplied. During
 		 * binary upgrade, all pg_enum.oid's are set this way so they are
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index f614915abfb..f1329f87e10 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -126,9 +126,14 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 	 */
 	tup = heap_form_tuple(tupDesc, values, nulls);
 
-	/* Use binary-upgrade override for pg_type.oid, if supplied. */
-	if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid))
+	/* Use binary-upgrade override for pg_type.oid? */
+	if (IsBinaryUpgrade)
 	{
+		if (!OidIsValid(binary_upgrade_next_pg_type_oid))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("pg_type OID value not set when in binary upgrade mode")));
+
 		HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
 		binary_upgrade_next_pg_type_oid = InvalidOid;
 	}
@@ -437,8 +442,13 @@ TypeCreate(Oid newTypeOid,
 		if (OidIsValid(newTypeOid))
 			HeapTupleSetOid(tup, newTypeOid);
 		/* Use binary-upgrade override for pg_type.oid, if supplied. */
-		else if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid))
+		else if (IsBinaryUpgrade)
 		{
+			if (!OidIsValid(binary_upgrade_next_pg_type_oid))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("pg_type OID value not set when in binary upgrade mode")));
+
 			HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
 			binary_upgrade_next_pg_type_oid = InvalidOid;
 		}
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index c8e7ea852cb..160f006ecdf 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -259,7 +259,11 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 	else
 		namespaceid = PG_TOAST_NAMESPACE;
 
-	/* Use binary-upgrade override for pg_type.oid, if supplied. */
+	/*
+	 * Use binary-upgrade override for pg_type.oid, if supplied.  We might
+	 * be in the post-schema-restore phase where we are doing ALTER TABLE
+	 * to create TOAST tables that didn't exist in the old cluster.
+	 */
 	if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_toast_pg_type_oid))
 	{
 		toast_typid = binary_upgrade_next_toast_pg_type_oid;
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index ec439fabd63..ad364efbcbd 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1986,9 +1986,14 @@ AssignTypeArrayOid(void)
 {
 	Oid			type_array_oid;
 
-	/* Use binary-upgrade override for pg_type.typarray, if supplied. */
-	if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_array_pg_type_oid))
+	/* Use binary-upgrade override for pg_type.typarray? */
+	if (IsBinaryUpgrade)
 	{
+		if (!OidIsValid(binary_upgrade_next_array_pg_type_oid))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("pg_type array OID value not set when in binary upgrade mode")));
+
 		type_array_oid = binary_upgrade_next_array_pg_type_oid;
 		binary_upgrade_next_array_pg_type_oid = InvalidOid;
 	}
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index d3a2044191b..91b6fa5c17d 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -379,10 +379,15 @@ CreateRole(CreateRoleStmt *stmt)
 
 	/*
 	 * pg_largeobject_metadata contains pg_authid.oid's, so we use the
-	 * binary-upgrade override, if specified.
+	 * binary-upgrade override.
 	 */
-	if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_authid_oid))
+	if (IsBinaryUpgrade)
 	{
+		if (!OidIsValid(binary_upgrade_next_pg_authid_oid))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("pg_authid OID value not set when in binary upgrade mode")));
+
 		HeapTupleSetOid(tuple, binary_upgrade_next_pg_authid_oid);
 		binary_upgrade_next_pg_authid_oid = InvalidOid;
 	}
-- 
GitLab