From 2ce2f89c0b182b17409ae531c2e1325cfadc477e Mon Sep 17 00:00:00 2001
From: Rui Zhao <xiyuan.zr@alibaba-inc.com>
Date: Tue, 8 Aug 2023 11:39:51 +0800
Subject: [PATCH] Fix pg_upgrade with in-place tablespaces.

---
 src/bin/pg_dump/pg_dumpall.c           | 12 +++++++++++-
 src/bin/pg_upgrade/t/002_pg_upgrade.pl |  5 +++++
 src/bin/pg_upgrade/tablespace.c        |  4 +++-
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 2cad796d3f..6466606444 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -1280,13 +1280,23 @@ dumpTablespaces(PGconn *conn)
 		{
 			appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_tablespace oid\n");
 			appendPQExpBuffer(buf, "SELECT pg_catalog.binary_upgrade_set_next_pg_tablespace_oid('%u'::pg_catalog.oid);\n", spcoid);
+
+			/* Allow to create in-place tablespace only for binary upgrade. */
+			if (!is_absolute_path(spclocation))
+				appendPQExpBuffer(buf, "SET allow_in_place_tablespaces = true;\n");
 		}
 
 		appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
 		appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
 
 		appendPQExpBufferStr(buf, " LOCATION ");
-		appendStringLiteralConn(buf, spclocation, conn);
+
+		/* In-place tablespaces use a relative path */
+		if (is_absolute_path(spclocation))
+			appendStringLiteralConn(buf, spclocation, conn);
+		else
+			appendStringLiteralConn(buf, "", conn);
+
 		appendPQExpBufferStr(buf, ";\n");
 
 		if (spcoptions && spcoptions[0] != '\0')
diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
index a5688a1cf2..ac9acced9f 100644
--- a/src/bin/pg_upgrade/t/002_pg_upgrade.pl
+++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
@@ -212,6 +212,11 @@ else
 	is($rc, 0, 'regression tests pass');
 }
 
+# Test with in-place tablespace.
+$oldnode->append_conf('postgresql.conf', 'allow_in_place_tablespaces = on');
+$oldnode->reload;
+$oldnode->safe_psql('postgres', "CREATE TABLESPACE space_test LOCATION ''");
+
 # Initialize a new node for the upgrade.
 my $newnode = PostgreSQL::Test::Cluster->new('new_node');
 
diff --git a/src/bin/pg_upgrade/tablespace.c b/src/bin/pg_upgrade/tablespace.c
index 69cef7fa6b..f38c3f92e3 100644
--- a/src/bin/pg_upgrade/tablespace.c
+++ b/src/bin/pg_upgrade/tablespace.c
@@ -45,11 +45,13 @@ get_tablespace_paths(void)
 	int			i_spclocation;
 	char		query[QUERY_ALLOC];
 
+	/* No need to check in-place tablespace. */
 	snprintf(query, sizeof(query),
 			 "SELECT pg_catalog.pg_tablespace_location(oid) AS spclocation "
 			 "FROM	pg_catalog.pg_tablespace "
 			 "WHERE	spcname != 'pg_default' AND "
-			 "		spcname != 'pg_global'");
+			 "		spcname != 'pg_global' AND "
+			 "		pg_catalog.pg_tablespace_location(oid) != 'pg_tblspc/' || oid");
 
 	res = executeQueryOrDie(conn, "%s", query);
 
-- 
2.32.0.3.g01195cf9f

