From 7448f487868b34bb333faaa278985721786b9a0e Mon Sep 17 00:00:00 2001 From: Rui Zhao Date: Fri, 18 Aug 2023 22:31:03 +0800 Subject: [PATCH] Fix pg_upgrade with in-place tablespaces. --- src/bin/pg_upgrade/t/002_pg_upgrade.pl | 44 ++++++++++++++++++++++++++ src/bin/pg_upgrade/tablespace.c | 23 ++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl index a5688a1cf2..1521bb7bb7 100644 --- a/src/bin/pg_upgrade/t/002_pg_upgrade.pl +++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl @@ -371,6 +371,50 @@ $oldnode->start; $oldnode->safe_psql('postgres', 'DROP DATABASE regression_invalid'); $oldnode->stop; +# Create an in-place tablespace, will be deleted below +$oldnode->start; +$oldnode->safe_psql('postgres', qq( + SET allow_in_place_tablespaces = on; + CREATE TABLESPACE space_test LOCATION ''; +)); +$oldnode->stop; + +# Check that pg_upgrade fails without allow_in_place_tablespaces option +command_checks_all( + [ + 'pg_upgrade', '--no-sync', '-d', $oldnode->data_dir, + '-D', $newnode->data_dir, '-b', $oldbindir, + '-B', $newbindir, '-s', $newnode->host, + '-p', $oldnode->port, '-P', $newnode->port, + $mode, '--check', + ], + 1, + [qr/Disable to upgrade with in-place tablespaces, you can enable it with --old-options="-c allow_in_place_tablespaces=on"/], + [qr//], + 'fail to upgrade with in-place tablespaces'); +ok(-d $newnode->data_dir . "/pg_upgrade_output.d", + "pg_upgrade_output.d/ not removed after pg_upgrade failure"); +rmtree($newnode->data_dir . "/pg_upgrade_output.d"); + +# Check that pg_upgrade succeeds with allow_in_place_tablespaces option +command_ok( + [ + 'pg_upgrade', '--no-sync', '-d', $oldnode->data_dir, + '-D', $newnode->data_dir, '-b', $oldbindir, + '-B', $newbindir, '-s', $newnode->host, + '-p', $oldnode->port, '-P', $newnode->port, + '-o', '-c allow_in_place_tablespaces=on', + $mode, '--check', + ], + 'succeed to upgrade with in-place tablespaces'); +ok(!-d $newnode->data_dir . "/pg_upgrade_output.d", + "pg_upgrade_output.d/ removed after pg_upgrade --check success"); + +# And drop in-place tablespace, so we can continue +$oldnode->start; +$oldnode->safe_psql('postgres', 'DROP TABLESPACE space_test'); +$oldnode->stop; + # --check command works here, cleans up pg_upgrade_output.d. command_ok( [ diff --git a/src/bin/pg_upgrade/tablespace.c b/src/bin/pg_upgrade/tablespace.c index 69cef7fa6b..945391c8b1 100644 --- a/src/bin/pg_upgrade/tablespace.c +++ b/src/bin/pg_upgrade/tablespace.c @@ -44,6 +44,15 @@ get_tablespace_paths(void) int tblnum; int i_spclocation; char query[QUERY_ALLOC]; + bool allow_in_place_tablespaces; + + snprintf(query, sizeof(query), + "SELECT setting FROM pg_settings WHERE " + "name = 'allow_in_place_tablespaces'"); + + res = executeQueryOrDie(conn, "%s", query); + allow_in_place_tablespaces = (strcmp(PQgetvalue(res, 0, 0), "on") == 0); + PQclear(res); snprintf(query, sizeof(query), "SELECT pg_catalog.pg_tablespace_location(oid) AS spclocation " @@ -51,6 +60,14 @@ get_tablespace_paths(void) "WHERE spcname != 'pg_default' AND " " spcname != 'pg_global'"); + /* + * No need to check in-place tablespaces when allow_in_place_tablespaces is + * on because they are part of the data folder. + */ + if (allow_in_place_tablespaces) + snprintf(query, sizeof(query), + "%s AND pg_catalog.pg_tablespace_location(oid) != 'pg_tblspc/' || oid", query); + res = executeQueryOrDie(conn, "%s", query); if ((os_info.num_old_tablespaces = PQntuples(res)) != 0) @@ -67,6 +84,12 @@ get_tablespace_paths(void) os_info.old_tablespaces[tblnum] = pg_strdup(PQgetvalue(res, tblnum, i_spclocation)); + if (!is_absolute_path(os_info.old_tablespaces[tblnum])) + report_status(PG_FATAL, + "Disable to upgrade with in-place tablespaces, " + "you can enable it with " + "--old-options=\"-c allow_in_place_tablespaces=on\""); + /* * Check that the tablespace path exists and is a directory. * Effectively, this is checking only for tables/indexes in -- 2.32.0.3.g01195cf9f