agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH 3/3] Avoid GIN full scan for non-empty ALL keys 65+ messages / 3 participants [nested] [flat]
* [PATCH 3/3] Avoid GIN full scan for non-empty ALL keys @ 2019-08-02 22:59 Nikita Glukhov <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nikita Glukhov @ 2019-08-02 22:59 UTC (permalink / raw) --- src/backend/access/gin/ginget.c | 3 +- src/backend/access/gin/ginscan.c | 56 ++++++++++++++++++++++++++++++++--- src/backend/utils/adt/selfuncs.c | 54 +++++++++++++++++---------------- src/include/access/gin_private.h | 2 ++ src/test/regress/expected/tsearch.out | 24 +++++++++++++++ src/test/regress/sql/tsearch.sql | 7 +++++ 6 files changed, 116 insertions(+), 30 deletions(-) diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index 65ed8b2..acc43c1 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -588,7 +588,8 @@ startScan(IndexScanDesc scan) uint32 i; for (i = 0; i < so->totalentries; i++) - startScanEntry(ginstate, so->entries[i], scan->xs_snapshot); + if (so->entries[i]->nrefs > 0) + startScanEntry(ginstate, so->entries[i], scan->xs_snapshot); if (GinFuzzySearchLimit > 0) { diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c index f612e55..605cc5f 100644 --- a/src/backend/access/gin/ginscan.c +++ b/src/backend/access/gin/ginscan.c @@ -87,6 +87,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum, queryCategory) == 0) { /* Successful match */ + prevEntry->nrefs++; return prevEntry; } } @@ -94,6 +95,9 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum, /* Nope, create a new entry */ scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData)); + + scanEntry->nrefs = 1; + scanEntry->queryKey = queryKey; scanEntry->queryCategory = queryCategory; scanEntry->isPartialMatch = isPartialMatch; @@ -273,6 +277,8 @@ ginNewScanKey(IndexScanDesc scan) GinScanOpaque so = (GinScanOpaque) scan->opaque; int i; bool hasNullQuery = false; + bool hasAllQuery = false; + bool hasNormalQuery = false; int numColsNeedNotNull = 0; bool colNeedsNotNull[INDEX_MAX_KEYS] = {0}; bool colImpliesNotNull[INDEX_MAX_KEYS] = {0}; @@ -390,6 +396,11 @@ ginNewScanKey(IndexScanDesc scan) if (searchMode != GIN_SEARCH_MODE_DEFAULT) hasNullQuery = true; + if (searchMode == GIN_SEARCH_MODE_ALL) + hasAllQuery = true; + else + hasNormalQuery = true; + /* * Create GinNullCategory representation. If the extractQueryFn * didn't create a nullFlags array, we assume everything is non-null. @@ -467,13 +478,50 @@ ginNewScanKey(IndexScanDesc scan) } } } - else if (numColsNeedNotNull > 0) + else { + if (numColsNeedNotNull > 0) + { + /* + * We use recheck instead of adding NOT_NULL entries to eliminate + * rows with NULL columns. + */ + so->forcedRecheck = true; + } + /* - * We use recheck instead of adding NOT_NULL entries to eliminate - * rows with NULL columns. + * If we have both ALL and normal keys, then remove ALL keys and + * force recheck. */ - so->forcedRecheck = true; + if (hasAllQuery && hasNormalQuery) + { + int nkeys = so->nkeys; + int j = 0; + + for (i = 0; i < nkeys; i++) + { + GinScanKey key = &so->keys[i]; + + if (key->searchMode == GIN_SEARCH_MODE_ALL) + { + /* Derefence key's entries */ + for (int e = 0; e < key->nentries; e++) + key->scanEntry[e]->nrefs--; + + so->nkeys--; + } + else + { + /* Move key */ + if (i != j) + so->keys[j] = so->keys[i]; + + j++; + } + } + + so->forcedRecheck = true; + } } } diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 1a9d76d..dcdd636 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -6245,6 +6245,7 @@ spgcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, typedef struct { bool haveFullScan; + bool haveNormalScan; double partialEntries; double exactEntries; double searchEntries; @@ -6326,40 +6327,42 @@ gincost_pattern(IndexOptInfo *index, int indexcol, return false; } - if (nentries <= 0 && searchMode == GIN_SEARCH_MODE_ALL) + if (searchMode == GIN_SEARCH_MODE_ALL) { /* * GIN does not emit scan entries for empty GIN_SEARCH_MODE_ALL keys, * and it can avoid full index scan if there are entries from other * keys, so we can skip setting of 'haveFullScan' flag. */ - return true; - } + if (nentries <= 0) + return true; - for (i = 0; i < nentries; i++) + counts->haveFullScan = true; + } + else { - /* - * For partial match we haven't any information to estimate number of - * matched entries in index, so, we just estimate it as 100 - */ - if (partial_matches && partial_matches[i]) - counts->partialEntries += 100; - else - counts->exactEntries++; + counts->haveNormalScan = true; - counts->searchEntries++; - } + for (i = 0; i < nentries; i++) + { + /* + * For partial match we haven't any information to estimate number of + * matched entries in index, so, we just estimate it as 100 + */ + if (partial_matches && partial_matches[i]) + counts->partialEntries += 100; + else + counts->exactEntries++; - if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY) - { - /* Treat "include empty" like an exact-match item */ - counts->exactEntries++; - counts->searchEntries++; - } - else if (searchMode != GIN_SEARCH_MODE_DEFAULT) - { - /* It's GIN_SEARCH_MODE_ALL */ - counts->haveFullScan = true; + counts->searchEntries++; + } + + if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY) + { + /* Treat "include empty" like an exact-match item */ + counts->exactEntries++; + counts->searchEntries++; + } } return true; @@ -6719,7 +6722,8 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, return; } - if (counts.haveFullScan || indexQuals == NIL || counts.searchEntries <= 0) + if ((counts.haveFullScan && !counts.haveNormalScan) || + indexQuals == NIL || counts.searchEntries <= 0) { /* * Full index scan will be required. We treat this as if every key in diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index b0251f7..af05964 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -313,6 +313,8 @@ typedef struct GinScanKeyData typedef struct GinScanEntryData { + /* Number of references from GinScanKeys */ + int nrefs; /* query key and other information from extractQueryFn */ Datum queryKey; GinNullCategory queryCategory; diff --git a/src/test/regress/expected/tsearch.out b/src/test/regress/expected/tsearch.out index 7af2899..3f19620 100644 --- a/src/test/regress/expected/tsearch.out +++ b/src/test/regress/expected/tsearch.out @@ -337,6 +337,30 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme'; 508 (1 row) +-- Test optimization of non-empty GIN_SEARCH_MODE_ALL queries +EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) +SELECT * FROM test_tsvector WHERE a @@ '!qh'; + QUERY PLAN +------------------------------------------------------------- + Bitmap Heap Scan on test_tsvector (actual rows=410 loops=1) + Recheck Cond: (a @@ '!''qh'''::tsquery) + Heap Blocks: exact=25 + -> Bitmap Index Scan on wowidx (actual rows=410 loops=1) + Index Cond: (a @@ '!''qh'''::tsquery) +(5 rows) + +EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) +SELECT * FROM test_tsvector WHERE a @@ 'wr' AND a @@ '!qh'; + QUERY PLAN +------------------------------------------------------------------------------ + Bitmap Heap Scan on test_tsvector (actual rows=60 loops=1) + Recheck Cond: ((a @@ '''wr'''::tsquery) AND (a @@ '!''qh'''::tsquery)) + Rows Removed by Index Recheck: 17 + Heap Blocks: exact=24 + -> Bitmap Index Scan on wowidx (actual rows=77 loops=1) + Index Cond: ((a @@ '''wr'''::tsquery) AND (a @@ '!''qh'''::tsquery)) +(6 rows) + RESET enable_seqscan; INSERT INTO test_tsvector VALUES ('???', 'DFG:1A,2B,6C,10 FGH'); SELECT * FROM ts_stat('SELECT a FROM test_tsvector') ORDER BY ndoc DESC, nentry DESC, word LIMIT 10; diff --git a/src/test/regress/sql/tsearch.sql b/src/test/regress/sql/tsearch.sql index ece80b9..54a5eef 100644 --- a/src/test/regress/sql/tsearch.sql +++ b/src/test/regress/sql/tsearch.sql @@ -111,6 +111,13 @@ SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}'); SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme'; SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme'; +-- Test optimization of non-empty GIN_SEARCH_MODE_ALL queries +EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) +SELECT * FROM test_tsvector WHERE a @@ '!qh'; + +EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) +SELECT * FROM test_tsvector WHERE a @@ 'wr' AND a @@ '!qh'; + RESET enable_seqscan; INSERT INTO test_tsvector VALUES ('???', 'DFG:1A,2B,6C,10 FGH'); -- 2.7.4 --------------B7A985DD4CDB1298897DF1B4-- ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 10/10] regress: Check for postgres startup completion more often @ 2023-08-07 23:51 Andres Freund <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Andres Freund @ 2023-08-07 23:51 UTC (permalink / raw) Previously pg_regress.c only checked whether the server started up once a second - in most cases startup is much faster though. Use the same interval as pg_ctl does. --- src/test/regress/pg_regress.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 407e3915cec..46af1fddbdb 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -75,6 +75,9 @@ const char *pretty_diff_opts = "-w -U3"; */ #define TESTNAME_WIDTH 36 +/* how often to recheck if postgres startup completed */ +#define WAITS_PER_SEC 10 + typedef enum TAPtype { DIAG = 0, @@ -2499,7 +2502,7 @@ regression_main(int argc, char *argv[], else wait_seconds = 60; - for (i = 0; i < wait_seconds; i++) + for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++) { /* Done if psql succeeds */ fflush(NULL); @@ -2519,7 +2522,7 @@ regression_main(int argc, char *argv[], outputdir); } - pg_usleep(1000000L); + pg_usleep(1000000L / WAITS_PER_SEC); } if (i >= wait_seconds) { -- 2.38.0 --uh2yukyzfvojbe2k-- ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v1 7/9] regress: Check for postgres startup completion more often @ 2023-08-07 23:51 Andres Freund <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Andres Freund @ 2023-08-07 23:51 UTC (permalink / raw) Previously pg_regress.c only checked whether the server started up once a second - in most cases startup is much faster though. Use the same interval as pg_ctl does. --- src/test/regress/pg_regress.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 407e3915cec..46af1fddbdb 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -75,6 +75,9 @@ const char *pretty_diff_opts = "-w -U3"; */ #define TESTNAME_WIDTH 36 +/* how often to recheck if postgres startup completed */ +#define WAITS_PER_SEC 10 + typedef enum TAPtype { DIAG = 0, @@ -2499,7 +2502,7 @@ regression_main(int argc, char *argv[], else wait_seconds = 60; - for (i = 0; i < wait_seconds; i++) + for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++) { /* Done if psql succeeds */ fflush(NULL); @@ -2519,7 +2522,7 @@ regression_main(int argc, char *argv[], outputdir); } - pg_usleep(1000000L); + pg_usleep(1000000L / WAITS_PER_SEC); } if (i >= wait_seconds) { -- 2.38.0 --uu4yojthqnm7ulmd Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0008-ci-Don-t-specify-amount-of-memory.patch" ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 10/10] regress: Check for postgres startup completion more often @ 2023-08-07 23:51 Andres Freund <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Andres Freund @ 2023-08-07 23:51 UTC (permalink / raw) Previously pg_regress.c only checked whether the server started up once a second - in most cases startup is much faster though. Use the same interval as pg_ctl does. --- src/test/regress/pg_regress.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 407e3915cec..46af1fddbdb 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -75,6 +75,9 @@ const char *pretty_diff_opts = "-w -U3"; */ #define TESTNAME_WIDTH 36 +/* how often to recheck if postgres startup completed */ +#define WAITS_PER_SEC 10 + typedef enum TAPtype { DIAG = 0, @@ -2499,7 +2502,7 @@ regression_main(int argc, char *argv[], else wait_seconds = 60; - for (i = 0; i < wait_seconds; i++) + for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++) { /* Done if psql succeeds */ fflush(NULL); @@ -2519,7 +2522,7 @@ regression_main(int argc, char *argv[], outputdir); } - pg_usleep(1000000L); + pg_usleep(1000000L / WAITS_PER_SEC); } if (i >= wait_seconds) { -- 2.38.0 --uh2yukyzfvojbe2k-- ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v1 7/9] regress: Check for postgres startup completion more often @ 2023-08-07 23:51 Andres Freund <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Andres Freund @ 2023-08-07 23:51 UTC (permalink / raw) Previously pg_regress.c only checked whether the server started up once a second - in most cases startup is much faster though. Use the same interval as pg_ctl does. --- src/test/regress/pg_regress.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 407e3915cec..46af1fddbdb 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -75,6 +75,9 @@ const char *pretty_diff_opts = "-w -U3"; */ #define TESTNAME_WIDTH 36 +/* how often to recheck if postgres startup completed */ +#define WAITS_PER_SEC 10 + typedef enum TAPtype { DIAG = 0, @@ -2499,7 +2502,7 @@ regression_main(int argc, char *argv[], else wait_seconds = 60; - for (i = 0; i < wait_seconds; i++) + for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++) { /* Done if psql succeeds */ fflush(NULL); @@ -2519,7 +2522,7 @@ regression_main(int argc, char *argv[], outputdir); } - pg_usleep(1000000L); + pg_usleep(1000000L / WAITS_PER_SEC); } if (i >= wait_seconds) { -- 2.38.0 --uu4yojthqnm7ulmd Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0008-ci-Don-t-specify-amount-of-memory.patch" ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v1 7/9] regress: Check for postgres startup completion more often @ 2023-08-07 23:51 Andres Freund <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Andres Freund @ 2023-08-07 23:51 UTC (permalink / raw) Previously pg_regress.c only checked whether the server started up once a second - in most cases startup is much faster though. Use the same interval as pg_ctl does. --- src/test/regress/pg_regress.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 407e3915cec..46af1fddbdb 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -75,6 +75,9 @@ const char *pretty_diff_opts = "-w -U3"; */ #define TESTNAME_WIDTH 36 +/* how often to recheck if postgres startup completed */ +#define WAITS_PER_SEC 10 + typedef enum TAPtype { DIAG = 0, @@ -2499,7 +2502,7 @@ regression_main(int argc, char *argv[], else wait_seconds = 60; - for (i = 0; i < wait_seconds; i++) + for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++) { /* Done if psql succeeds */ fflush(NULL); @@ -2519,7 +2522,7 @@ regression_main(int argc, char *argv[], outputdir); } - pg_usleep(1000000L); + pg_usleep(1000000L / WAITS_PER_SEC); } if (i >= wait_seconds) { -- 2.38.0 --uu4yojthqnm7ulmd Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0008-ci-Don-t-specify-amount-of-memory.patch" ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] Move x86 popcount code to pg_popcount_x86_64.c. @ 2026-01-14 17:54 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-01-14 17:54 UTC (permalink / raw) This moves the SSE4.2 popcount implementations to the recently renamed file for x86-64-specific popcount code. --- src/include/port/pg_bitutils.h | 20 ++- src/port/pg_bitutils.c | 263 +------------------------------- src/port/pg_popcount_x86.c | 264 +++++++++++++++++++++++++++++++-- 3 files changed, 267 insertions(+), 280 deletions(-) diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 8ed12f7a021..c9c508d4ba3 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -307,23 +307,21 @@ pg_ceil_log2_64(uint64 num) #define POPCNT_AARCH64 1 #endif +extern int pg_popcount32_slow(uint32 word); +extern int pg_popcount64_slow(uint64 word); +extern uint64 pg_popcount_slow(const char *buf, int bytes); +extern uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); + #ifdef TRY_POPCNT_X86_64 -/* Attempt to use the POPCNT instruction, but perform a runtime check first */ +/* + * Attempt to use SSE4.2 or AVX-512 instructions, but perform a runtime check + * first. + */ extern PGDLLIMPORT int (*pg_popcount32) (uint32 word); extern PGDLLIMPORT int (*pg_popcount64) (uint64 word); extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes); extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask); -/* - * We can also try to use the AVX-512 popcount instruction on some systems. - * The implementation of that is located in its own file. - */ -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK -extern bool pg_popcount_avx512_available(void); -extern uint64 pg_popcount_avx512(const char *buf, int bytes); -extern uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); -#endif - #elif POPCNT_AARCH64 /* Use the Neon version of pg_popcount{32,64} without function pointer. */ extern int pg_popcount32(uint32 word); diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 7875bbb0f4b..9f9f90ddd4d 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -12,13 +12,6 @@ */ #include "c.h" -#ifdef HAVE__GET_CPUID -#include <cpuid.h> -#endif -#ifdef HAVE__CPUID -#include <intrin.h> -#endif - #include "port/pg_bitutils.h" @@ -103,257 +96,11 @@ const uint8 pg_number_of_ones[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 -static inline int pg_popcount32_slow(uint32 word); -static inline int pg_popcount64_slow(uint64 word); -static uint64 pg_popcount_slow(const char *buf, int bytes); -static uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); -#endif - -#ifdef TRY_POPCNT_X86_64 -static bool pg_popcount_available(void); -static int pg_popcount32_choose(uint32 word); -static int pg_popcount64_choose(uint64 word); -static uint64 pg_popcount_choose(const char *buf, int bytes); -static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); -static inline int pg_popcount32_fast(uint32 word); -static inline int pg_popcount64_fast(uint64 word); -static uint64 pg_popcount_fast(const char *buf, int bytes); -static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); - -int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; -int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; -uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; -uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; -#endif /* TRY_POPCNT_X86_64 */ - -#ifdef TRY_POPCNT_X86_64 - -/* - * Return true if CPUID indicates that the POPCNT instruction is available. - */ -static bool -pg_popcount_available(void) -{ - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID) - __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUID) - __cpuid(exx, 1); -#else -#error cpuid instruction not available -#endif - - return (exx[2] & (1 << 23)) != 0; /* POPCNT */ -} - -/* - * These functions get called on the first call to pg_popcount32 etc. - * They detect whether we can use the asm implementations, and replace - * the function pointers so that subsequent calls are routed directly to - * the chosen implementation. - */ -static inline void -choose_popcount_functions(void) -{ - if (pg_popcount_available()) - { - pg_popcount32 = pg_popcount32_fast; - pg_popcount64 = pg_popcount64_fast; - pg_popcount_optimized = pg_popcount_fast; - pg_popcount_masked_optimized = pg_popcount_masked_fast; - } - else - { - pg_popcount32 = pg_popcount32_slow; - pg_popcount64 = pg_popcount64_slow; - pg_popcount_optimized = pg_popcount_slow; - pg_popcount_masked_optimized = pg_popcount_masked_slow; - } - -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK - if (pg_popcount_avx512_available()) - { - pg_popcount_optimized = pg_popcount_avx512; - pg_popcount_masked_optimized = pg_popcount_masked_avx512; - } -#endif -} - -static int -pg_popcount32_choose(uint32 word) -{ - choose_popcount_functions(); - return pg_popcount32(word); -} - -static int -pg_popcount64_choose(uint64 word) -{ - choose_popcount_functions(); - return pg_popcount64(word); -} - -static uint64 -pg_popcount_choose(const char *buf, int bytes) -{ - choose_popcount_functions(); - return pg_popcount_optimized(buf, bytes); -} - -static uint64 -pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) -{ - choose_popcount_functions(); - return pg_popcount_masked(buf, bytes, mask); -} - -/* - * pg_popcount32_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount32_fast(uint32 word) -{ -#ifdef _MSC_VER - return __popcnt(word); -#else - uint32 res; - -__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount64_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount64_fast(uint64 word) -{ -#ifdef _MSC_VER - return __popcnt64(word); -#else - uint64 res; - -__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount_fast - * Returns the number of 1-bits in buf - */ -static uint64 -pg_popcount_fast(const char *buf, int bytes) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++]; - - return popcnt; -} - -/* - * pg_popcount_masked_fast - * Returns the number of 1-bits in buf after applying the mask to each byte - */ -static uint64 -pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned */ - uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++ & maskv); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - uint32 maskv = ~((uint32) 0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++ & maskv); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; - - return popcnt; -} - -#endif /* TRY_POPCNT_X86_64 */ - -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 - /* * pg_popcount32_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount32_slow(uint32 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -375,7 +122,7 @@ pg_popcount32_slow(uint32 word) * pg_popcount64_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount64_slow(uint64 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -403,7 +150,7 @@ pg_popcount64_slow(uint64 word) * pg_popcount_slow * Returns the number of 1-bits in buf */ -static uint64 +uint64 pg_popcount_slow(const char *buf, int bytes) { uint64 popcnt = 0; @@ -449,7 +196,7 @@ pg_popcount_slow(const char *buf, int bytes) * pg_popcount_masked_slow * Returns the number of 1-bits in buf after applying the mask to each byte */ -static uint64 +uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) { uint64 popcnt = 0; @@ -495,8 +242,6 @@ pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) return popcnt; } -#endif /* ! POPCNT_AARCH64 */ - #if !defined(TRY_POPCNT_X86_64) && !defined(POPCNT_AARCH64) /* diff --git a/src/port/pg_popcount_x86.c b/src/port/pg_popcount_x86.c index 453c7a06ce9..f8643642613 100644 --- a/src/port/pg_popcount_x86.c +++ b/src/port/pg_popcount_x86.c @@ -12,26 +12,74 @@ */ #include "c.h" -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +#include "port/pg_bitutils.h" + +#ifdef TRY_POPCNT_X86_64 #if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) #include <cpuid.h> #endif +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK #include <immintrin.h> +#endif #if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) #include <intrin.h> #endif -#include "port/pg_bitutils.h" +/* + * The SSE4.2 versions are built regardless of whether we are building the + * AVX-512 versions. + */ +static inline int pg_popcount32_fast(uint32 word); +static inline int pg_popcount64_fast(uint64 word); +static uint64 pg_popcount_fast(const char *buf, int bytes); +static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); /* - * It's probably unlikely that TRY_POPCNT_X86_64 won't be set if we are able to - * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on - * the function pointers that are only used when TRY_POPCNT_X86_64 is set. + * These are the AVX-512 implementations of the popcount functions. */ -#ifdef TRY_POPCNT_X86_64 +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +static uint64 pg_popcount_avx512(const char *buf, int bytes); +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * The function pointers are initially set to "choose" functions. These + * functions will first set the pointers to the right implementations (base on + * what the current CPU supports) and then will call the pointer to fulfill the + * caller's request. + */ +static int pg_popcount32_choose(uint32 word); +static int pg_popcount64_choose(uint64 word); +static uint64 pg_popcount_choose(const char *buf, int bytes); +static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); +int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; +int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; +uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; +uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; + +/* + * Return true if CPUID indicates that the POPCNT instruction is available. + */ +static bool +pg_popcount_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + + return (exx[2] & (1 << 23)) != 0; /* POPCNT */ +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK /* * Does CPUID say there's support for XSAVE instructions? @@ -94,7 +142,7 @@ avx512_popcnt_available(void) * Returns true if the CPU supports the instructions required for the AVX-512 * pg_popcount() implementation. */ -bool +static bool pg_popcount_avx512_available(void) { return xsave_available() && @@ -102,12 +150,77 @@ pg_popcount_avx512_available(void) avx512_popcnt_available(); } +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * These functions get called on the first call to pg_popcount32 etc. + * They detect whether we can use the asm implementations, and replace + * the function pointers so that subsequent calls are routed directly to + * the chosen implementation. + */ +static inline void +choose_popcount_functions(void) +{ + if (pg_popcount_available()) + { + pg_popcount32 = pg_popcount32_fast; + pg_popcount64 = pg_popcount64_fast; + pg_popcount_optimized = pg_popcount_fast; + pg_popcount_masked_optimized = pg_popcount_masked_fast; + } + else + { + pg_popcount32 = pg_popcount32_slow; + pg_popcount64 = pg_popcount64_slow; + pg_popcount_optimized = pg_popcount_slow; + pg_popcount_masked_optimized = pg_popcount_masked_slow; + } + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + if (pg_popcount_avx512_available()) + { + pg_popcount_optimized = pg_popcount_avx512; + pg_popcount_masked_optimized = pg_popcount_masked_avx512; + } +#endif +} + +static int +pg_popcount32_choose(uint32 word) +{ + choose_popcount_functions(); + return pg_popcount32(word); +} + +static int +pg_popcount64_choose(uint64 word) +{ + choose_popcount_functions(); + return pg_popcount64(word); +} + +static uint64 +pg_popcount_choose(const char *buf, int bytes) +{ + choose_popcount_functions(); + return pg_popcount_optimized(buf, bytes); +} + +static uint64 +pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) +{ + choose_popcount_functions(); + return pg_popcount_masked(buf, bytes, mask); +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + /* * pg_popcount_avx512 * Returns the number of 1-bits in buf */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_avx512(const char *buf, int bytes) { __m512i val, @@ -163,7 +276,7 @@ pg_popcount_avx512(const char *buf, int bytes) * Returns the number of 1-bits in buf after applying the mask to each byte */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) { __m512i val, @@ -219,5 +332,136 @@ pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) return _mm512_reduce_add_epi64(accum); } -#endif /* TRY_POPCNT_X86_64 */ #endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * pg_popcount32_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount32_fast(uint32 word) +{ +#ifdef _MSC_VER + return __popcnt(word); +#else + uint32 res; + +__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount64_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount64_fast(uint64 word) +{ +#ifdef _MSC_VER + return __popcnt64(word); +#else + uint64 res; + +__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount_fast + * Returns the number of 1-bits in buf + */ +static uint64 +pg_popcount_fast(const char *buf, int bytes) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++]; + + return popcnt; +} + +/* + * pg_popcount_masked_fast + * Returns the number of 1-bits in buf after applying the mask to each byte + */ +static uint64 +pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned */ + uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++ & maskv); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + uint32 maskv = ~((uint32) 0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++ & maskv); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; + + return popcnt; +} + +#endif /* TRY_POPCNT_X86_64 */ -- 2.50.1 (Apple Git-155) --KuW0xlRTZoVkcm/J Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-Rename-fast-and-slow-popcount-functions.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v1 2/3] Move x86 popcount code to pg_popcount_x86_64.c. @ 2026-01-14 17:54 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-01-14 17:54 UTC (permalink / raw) This moves the SSE4.2 popcount implementations to the recently renamed file for x86-64-specific popcount code. --- src/include/port/pg_bitutils.h | 20 ++- src/port/pg_bitutils.c | 263 +------------------------------- src/port/pg_popcount_x86_64.c | 264 +++++++++++++++++++++++++++++++-- 3 files changed, 267 insertions(+), 280 deletions(-) diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 8ed12f7a021..c9c508d4ba3 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -307,23 +307,21 @@ pg_ceil_log2_64(uint64 num) #define POPCNT_AARCH64 1 #endif +extern int pg_popcount32_slow(uint32 word); +extern int pg_popcount64_slow(uint64 word); +extern uint64 pg_popcount_slow(const char *buf, int bytes); +extern uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); + #ifdef TRY_POPCNT_X86_64 -/* Attempt to use the POPCNT instruction, but perform a runtime check first */ +/* + * Attempt to use SSE4.2 or AVX-512 instructions, but perform a runtime check + * first. + */ extern PGDLLIMPORT int (*pg_popcount32) (uint32 word); extern PGDLLIMPORT int (*pg_popcount64) (uint64 word); extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes); extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask); -/* - * We can also try to use the AVX-512 popcount instruction on some systems. - * The implementation of that is located in its own file. - */ -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK -extern bool pg_popcount_avx512_available(void); -extern uint64 pg_popcount_avx512(const char *buf, int bytes); -extern uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); -#endif - #elif POPCNT_AARCH64 /* Use the Neon version of pg_popcount{32,64} without function pointer. */ extern int pg_popcount32(uint32 word); diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 7875bbb0f4b..9f9f90ddd4d 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -12,13 +12,6 @@ */ #include "c.h" -#ifdef HAVE__GET_CPUID -#include <cpuid.h> -#endif -#ifdef HAVE__CPUID -#include <intrin.h> -#endif - #include "port/pg_bitutils.h" @@ -103,257 +96,11 @@ const uint8 pg_number_of_ones[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 -static inline int pg_popcount32_slow(uint32 word); -static inline int pg_popcount64_slow(uint64 word); -static uint64 pg_popcount_slow(const char *buf, int bytes); -static uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); -#endif - -#ifdef TRY_POPCNT_X86_64 -static bool pg_popcount_available(void); -static int pg_popcount32_choose(uint32 word); -static int pg_popcount64_choose(uint64 word); -static uint64 pg_popcount_choose(const char *buf, int bytes); -static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); -static inline int pg_popcount32_fast(uint32 word); -static inline int pg_popcount64_fast(uint64 word); -static uint64 pg_popcount_fast(const char *buf, int bytes); -static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); - -int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; -int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; -uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; -uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; -#endif /* TRY_POPCNT_X86_64 */ - -#ifdef TRY_POPCNT_X86_64 - -/* - * Return true if CPUID indicates that the POPCNT instruction is available. - */ -static bool -pg_popcount_available(void) -{ - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID) - __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUID) - __cpuid(exx, 1); -#else -#error cpuid instruction not available -#endif - - return (exx[2] & (1 << 23)) != 0; /* POPCNT */ -} - -/* - * These functions get called on the first call to pg_popcount32 etc. - * They detect whether we can use the asm implementations, and replace - * the function pointers so that subsequent calls are routed directly to - * the chosen implementation. - */ -static inline void -choose_popcount_functions(void) -{ - if (pg_popcount_available()) - { - pg_popcount32 = pg_popcount32_fast; - pg_popcount64 = pg_popcount64_fast; - pg_popcount_optimized = pg_popcount_fast; - pg_popcount_masked_optimized = pg_popcount_masked_fast; - } - else - { - pg_popcount32 = pg_popcount32_slow; - pg_popcount64 = pg_popcount64_slow; - pg_popcount_optimized = pg_popcount_slow; - pg_popcount_masked_optimized = pg_popcount_masked_slow; - } - -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK - if (pg_popcount_avx512_available()) - { - pg_popcount_optimized = pg_popcount_avx512; - pg_popcount_masked_optimized = pg_popcount_masked_avx512; - } -#endif -} - -static int -pg_popcount32_choose(uint32 word) -{ - choose_popcount_functions(); - return pg_popcount32(word); -} - -static int -pg_popcount64_choose(uint64 word) -{ - choose_popcount_functions(); - return pg_popcount64(word); -} - -static uint64 -pg_popcount_choose(const char *buf, int bytes) -{ - choose_popcount_functions(); - return pg_popcount_optimized(buf, bytes); -} - -static uint64 -pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) -{ - choose_popcount_functions(); - return pg_popcount_masked(buf, bytes, mask); -} - -/* - * pg_popcount32_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount32_fast(uint32 word) -{ -#ifdef _MSC_VER - return __popcnt(word); -#else - uint32 res; - -__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount64_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount64_fast(uint64 word) -{ -#ifdef _MSC_VER - return __popcnt64(word); -#else - uint64 res; - -__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount_fast - * Returns the number of 1-bits in buf - */ -static uint64 -pg_popcount_fast(const char *buf, int bytes) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++]; - - return popcnt; -} - -/* - * pg_popcount_masked_fast - * Returns the number of 1-bits in buf after applying the mask to each byte - */ -static uint64 -pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned */ - uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++ & maskv); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - uint32 maskv = ~((uint32) 0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++ & maskv); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; - - return popcnt; -} - -#endif /* TRY_POPCNT_X86_64 */ - -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 - /* * pg_popcount32_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount32_slow(uint32 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -375,7 +122,7 @@ pg_popcount32_slow(uint32 word) * pg_popcount64_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount64_slow(uint64 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -403,7 +150,7 @@ pg_popcount64_slow(uint64 word) * pg_popcount_slow * Returns the number of 1-bits in buf */ -static uint64 +uint64 pg_popcount_slow(const char *buf, int bytes) { uint64 popcnt = 0; @@ -449,7 +196,7 @@ pg_popcount_slow(const char *buf, int bytes) * pg_popcount_masked_slow * Returns the number of 1-bits in buf after applying the mask to each byte */ -static uint64 +uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) { uint64 popcnt = 0; @@ -495,8 +242,6 @@ pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) return popcnt; } -#endif /* ! POPCNT_AARCH64 */ - #if !defined(TRY_POPCNT_X86_64) && !defined(POPCNT_AARCH64) /* diff --git a/src/port/pg_popcount_x86_64.c b/src/port/pg_popcount_x86_64.c index 453c7a06ce9..f8643642613 100644 --- a/src/port/pg_popcount_x86_64.c +++ b/src/port/pg_popcount_x86_64.c @@ -12,26 +12,74 @@ */ #include "c.h" -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +#include "port/pg_bitutils.h" + +#ifdef TRY_POPCNT_X86_64 #if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) #include <cpuid.h> #endif +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK #include <immintrin.h> +#endif #if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) #include <intrin.h> #endif -#include "port/pg_bitutils.h" +/* + * The SSE4.2 versions are built regardless of whether we are building the + * AVX-512 versions. + */ +static inline int pg_popcount32_fast(uint32 word); +static inline int pg_popcount64_fast(uint64 word); +static uint64 pg_popcount_fast(const char *buf, int bytes); +static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); /* - * It's probably unlikely that TRY_POPCNT_X86_64 won't be set if we are able to - * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on - * the function pointers that are only used when TRY_POPCNT_X86_64 is set. + * These are the AVX-512 implementations of the popcount functions. */ -#ifdef TRY_POPCNT_X86_64 +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +static uint64 pg_popcount_avx512(const char *buf, int bytes); +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * The function pointers are initially set to "choose" functions. These + * functions will first set the pointers to the right implementations (base on + * what the current CPU supports) and then will call the pointer to fulfill the + * caller's request. + */ +static int pg_popcount32_choose(uint32 word); +static int pg_popcount64_choose(uint64 word); +static uint64 pg_popcount_choose(const char *buf, int bytes); +static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); +int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; +int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; +uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; +uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; + +/* + * Return true if CPUID indicates that the POPCNT instruction is available. + */ +static bool +pg_popcount_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + + return (exx[2] & (1 << 23)) != 0; /* POPCNT */ +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK /* * Does CPUID say there's support for XSAVE instructions? @@ -94,7 +142,7 @@ avx512_popcnt_available(void) * Returns true if the CPU supports the instructions required for the AVX-512 * pg_popcount() implementation. */ -bool +static bool pg_popcount_avx512_available(void) { return xsave_available() && @@ -102,12 +150,77 @@ pg_popcount_avx512_available(void) avx512_popcnt_available(); } +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * These functions get called on the first call to pg_popcount32 etc. + * They detect whether we can use the asm implementations, and replace + * the function pointers so that subsequent calls are routed directly to + * the chosen implementation. + */ +static inline void +choose_popcount_functions(void) +{ + if (pg_popcount_available()) + { + pg_popcount32 = pg_popcount32_fast; + pg_popcount64 = pg_popcount64_fast; + pg_popcount_optimized = pg_popcount_fast; + pg_popcount_masked_optimized = pg_popcount_masked_fast; + } + else + { + pg_popcount32 = pg_popcount32_slow; + pg_popcount64 = pg_popcount64_slow; + pg_popcount_optimized = pg_popcount_slow; + pg_popcount_masked_optimized = pg_popcount_masked_slow; + } + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + if (pg_popcount_avx512_available()) + { + pg_popcount_optimized = pg_popcount_avx512; + pg_popcount_masked_optimized = pg_popcount_masked_avx512; + } +#endif +} + +static int +pg_popcount32_choose(uint32 word) +{ + choose_popcount_functions(); + return pg_popcount32(word); +} + +static int +pg_popcount64_choose(uint64 word) +{ + choose_popcount_functions(); + return pg_popcount64(word); +} + +static uint64 +pg_popcount_choose(const char *buf, int bytes) +{ + choose_popcount_functions(); + return pg_popcount_optimized(buf, bytes); +} + +static uint64 +pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) +{ + choose_popcount_functions(); + return pg_popcount_masked(buf, bytes, mask); +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + /* * pg_popcount_avx512 * Returns the number of 1-bits in buf */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_avx512(const char *buf, int bytes) { __m512i val, @@ -163,7 +276,7 @@ pg_popcount_avx512(const char *buf, int bytes) * Returns the number of 1-bits in buf after applying the mask to each byte */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) { __m512i val, @@ -219,5 +332,136 @@ pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) return _mm512_reduce_add_epi64(accum); } -#endif /* TRY_POPCNT_X86_64 */ #endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * pg_popcount32_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount32_fast(uint32 word) +{ +#ifdef _MSC_VER + return __popcnt(word); +#else + uint32 res; + +__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount64_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount64_fast(uint64 word) +{ +#ifdef _MSC_VER + return __popcnt64(word); +#else + uint64 res; + +__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount_fast + * Returns the number of 1-bits in buf + */ +static uint64 +pg_popcount_fast(const char *buf, int bytes) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++]; + + return popcnt; +} + +/* + * pg_popcount_masked_fast + * Returns the number of 1-bits in buf after applying the mask to each byte + */ +static uint64 +pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned */ + uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++ & maskv); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + uint32 maskv = ~((uint32) 0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++ & maskv); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; + + return popcnt; +} + +#endif /* TRY_POPCNT_X86_64 */ -- 2.50.1 (Apple Git-155) --RzZ1MyDExwO9gtVK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v1-0003-Rename-fast-and-slow-popcount-functions.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] Move x86 popcount code to pg_popcount_x86_64.c. @ 2026-01-14 17:54 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-01-14 17:54 UTC (permalink / raw) This moves the SSE4.2 popcount implementations to the recently renamed file for x86-64-specific popcount code. --- src/include/port/pg_bitutils.h | 20 ++- src/port/pg_bitutils.c | 263 +------------------------------- src/port/pg_popcount_x86.c | 264 +++++++++++++++++++++++++++++++-- 3 files changed, 267 insertions(+), 280 deletions(-) diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 8ed12f7a021..c9c508d4ba3 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -307,23 +307,21 @@ pg_ceil_log2_64(uint64 num) #define POPCNT_AARCH64 1 #endif +extern int pg_popcount32_slow(uint32 word); +extern int pg_popcount64_slow(uint64 word); +extern uint64 pg_popcount_slow(const char *buf, int bytes); +extern uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); + #ifdef TRY_POPCNT_X86_64 -/* Attempt to use the POPCNT instruction, but perform a runtime check first */ +/* + * Attempt to use SSE4.2 or AVX-512 instructions, but perform a runtime check + * first. + */ extern PGDLLIMPORT int (*pg_popcount32) (uint32 word); extern PGDLLIMPORT int (*pg_popcount64) (uint64 word); extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes); extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask); -/* - * We can also try to use the AVX-512 popcount instruction on some systems. - * The implementation of that is located in its own file. - */ -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK -extern bool pg_popcount_avx512_available(void); -extern uint64 pg_popcount_avx512(const char *buf, int bytes); -extern uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); -#endif - #elif POPCNT_AARCH64 /* Use the Neon version of pg_popcount{32,64} without function pointer. */ extern int pg_popcount32(uint32 word); diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 7875bbb0f4b..9f9f90ddd4d 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -12,13 +12,6 @@ */ #include "c.h" -#ifdef HAVE__GET_CPUID -#include <cpuid.h> -#endif -#ifdef HAVE__CPUID -#include <intrin.h> -#endif - #include "port/pg_bitutils.h" @@ -103,257 +96,11 @@ const uint8 pg_number_of_ones[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 -static inline int pg_popcount32_slow(uint32 word); -static inline int pg_popcount64_slow(uint64 word); -static uint64 pg_popcount_slow(const char *buf, int bytes); -static uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); -#endif - -#ifdef TRY_POPCNT_X86_64 -static bool pg_popcount_available(void); -static int pg_popcount32_choose(uint32 word); -static int pg_popcount64_choose(uint64 word); -static uint64 pg_popcount_choose(const char *buf, int bytes); -static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); -static inline int pg_popcount32_fast(uint32 word); -static inline int pg_popcount64_fast(uint64 word); -static uint64 pg_popcount_fast(const char *buf, int bytes); -static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); - -int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; -int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; -uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; -uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; -#endif /* TRY_POPCNT_X86_64 */ - -#ifdef TRY_POPCNT_X86_64 - -/* - * Return true if CPUID indicates that the POPCNT instruction is available. - */ -static bool -pg_popcount_available(void) -{ - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID) - __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUID) - __cpuid(exx, 1); -#else -#error cpuid instruction not available -#endif - - return (exx[2] & (1 << 23)) != 0; /* POPCNT */ -} - -/* - * These functions get called on the first call to pg_popcount32 etc. - * They detect whether we can use the asm implementations, and replace - * the function pointers so that subsequent calls are routed directly to - * the chosen implementation. - */ -static inline void -choose_popcount_functions(void) -{ - if (pg_popcount_available()) - { - pg_popcount32 = pg_popcount32_fast; - pg_popcount64 = pg_popcount64_fast; - pg_popcount_optimized = pg_popcount_fast; - pg_popcount_masked_optimized = pg_popcount_masked_fast; - } - else - { - pg_popcount32 = pg_popcount32_slow; - pg_popcount64 = pg_popcount64_slow; - pg_popcount_optimized = pg_popcount_slow; - pg_popcount_masked_optimized = pg_popcount_masked_slow; - } - -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK - if (pg_popcount_avx512_available()) - { - pg_popcount_optimized = pg_popcount_avx512; - pg_popcount_masked_optimized = pg_popcount_masked_avx512; - } -#endif -} - -static int -pg_popcount32_choose(uint32 word) -{ - choose_popcount_functions(); - return pg_popcount32(word); -} - -static int -pg_popcount64_choose(uint64 word) -{ - choose_popcount_functions(); - return pg_popcount64(word); -} - -static uint64 -pg_popcount_choose(const char *buf, int bytes) -{ - choose_popcount_functions(); - return pg_popcount_optimized(buf, bytes); -} - -static uint64 -pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) -{ - choose_popcount_functions(); - return pg_popcount_masked(buf, bytes, mask); -} - -/* - * pg_popcount32_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount32_fast(uint32 word) -{ -#ifdef _MSC_VER - return __popcnt(word); -#else - uint32 res; - -__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount64_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount64_fast(uint64 word) -{ -#ifdef _MSC_VER - return __popcnt64(word); -#else - uint64 res; - -__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount_fast - * Returns the number of 1-bits in buf - */ -static uint64 -pg_popcount_fast(const char *buf, int bytes) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++]; - - return popcnt; -} - -/* - * pg_popcount_masked_fast - * Returns the number of 1-bits in buf after applying the mask to each byte - */ -static uint64 -pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned */ - uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++ & maskv); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - uint32 maskv = ~((uint32) 0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++ & maskv); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; - - return popcnt; -} - -#endif /* TRY_POPCNT_X86_64 */ - -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 - /* * pg_popcount32_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount32_slow(uint32 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -375,7 +122,7 @@ pg_popcount32_slow(uint32 word) * pg_popcount64_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount64_slow(uint64 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -403,7 +150,7 @@ pg_popcount64_slow(uint64 word) * pg_popcount_slow * Returns the number of 1-bits in buf */ -static uint64 +uint64 pg_popcount_slow(const char *buf, int bytes) { uint64 popcnt = 0; @@ -449,7 +196,7 @@ pg_popcount_slow(const char *buf, int bytes) * pg_popcount_masked_slow * Returns the number of 1-bits in buf after applying the mask to each byte */ -static uint64 +uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) { uint64 popcnt = 0; @@ -495,8 +242,6 @@ pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) return popcnt; } -#endif /* ! POPCNT_AARCH64 */ - #if !defined(TRY_POPCNT_X86_64) && !defined(POPCNT_AARCH64) /* diff --git a/src/port/pg_popcount_x86.c b/src/port/pg_popcount_x86.c index 453c7a06ce9..f8643642613 100644 --- a/src/port/pg_popcount_x86.c +++ b/src/port/pg_popcount_x86.c @@ -12,26 +12,74 @@ */ #include "c.h" -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +#include "port/pg_bitutils.h" + +#ifdef TRY_POPCNT_X86_64 #if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) #include <cpuid.h> #endif +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK #include <immintrin.h> +#endif #if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) #include <intrin.h> #endif -#include "port/pg_bitutils.h" +/* + * The SSE4.2 versions are built regardless of whether we are building the + * AVX-512 versions. + */ +static inline int pg_popcount32_fast(uint32 word); +static inline int pg_popcount64_fast(uint64 word); +static uint64 pg_popcount_fast(const char *buf, int bytes); +static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); /* - * It's probably unlikely that TRY_POPCNT_X86_64 won't be set if we are able to - * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on - * the function pointers that are only used when TRY_POPCNT_X86_64 is set. + * These are the AVX-512 implementations of the popcount functions. */ -#ifdef TRY_POPCNT_X86_64 +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +static uint64 pg_popcount_avx512(const char *buf, int bytes); +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * The function pointers are initially set to "choose" functions. These + * functions will first set the pointers to the right implementations (base on + * what the current CPU supports) and then will call the pointer to fulfill the + * caller's request. + */ +static int pg_popcount32_choose(uint32 word); +static int pg_popcount64_choose(uint64 word); +static uint64 pg_popcount_choose(const char *buf, int bytes); +static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); +int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; +int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; +uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; +uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; + +/* + * Return true if CPUID indicates that the POPCNT instruction is available. + */ +static bool +pg_popcount_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + + return (exx[2] & (1 << 23)) != 0; /* POPCNT */ +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK /* * Does CPUID say there's support for XSAVE instructions? @@ -94,7 +142,7 @@ avx512_popcnt_available(void) * Returns true if the CPU supports the instructions required for the AVX-512 * pg_popcount() implementation. */ -bool +static bool pg_popcount_avx512_available(void) { return xsave_available() && @@ -102,12 +150,77 @@ pg_popcount_avx512_available(void) avx512_popcnt_available(); } +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * These functions get called on the first call to pg_popcount32 etc. + * They detect whether we can use the asm implementations, and replace + * the function pointers so that subsequent calls are routed directly to + * the chosen implementation. + */ +static inline void +choose_popcount_functions(void) +{ + if (pg_popcount_available()) + { + pg_popcount32 = pg_popcount32_fast; + pg_popcount64 = pg_popcount64_fast; + pg_popcount_optimized = pg_popcount_fast; + pg_popcount_masked_optimized = pg_popcount_masked_fast; + } + else + { + pg_popcount32 = pg_popcount32_slow; + pg_popcount64 = pg_popcount64_slow; + pg_popcount_optimized = pg_popcount_slow; + pg_popcount_masked_optimized = pg_popcount_masked_slow; + } + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + if (pg_popcount_avx512_available()) + { + pg_popcount_optimized = pg_popcount_avx512; + pg_popcount_masked_optimized = pg_popcount_masked_avx512; + } +#endif +} + +static int +pg_popcount32_choose(uint32 word) +{ + choose_popcount_functions(); + return pg_popcount32(word); +} + +static int +pg_popcount64_choose(uint64 word) +{ + choose_popcount_functions(); + return pg_popcount64(word); +} + +static uint64 +pg_popcount_choose(const char *buf, int bytes) +{ + choose_popcount_functions(); + return pg_popcount_optimized(buf, bytes); +} + +static uint64 +pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) +{ + choose_popcount_functions(); + return pg_popcount_masked(buf, bytes, mask); +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + /* * pg_popcount_avx512 * Returns the number of 1-bits in buf */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_avx512(const char *buf, int bytes) { __m512i val, @@ -163,7 +276,7 @@ pg_popcount_avx512(const char *buf, int bytes) * Returns the number of 1-bits in buf after applying the mask to each byte */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) { __m512i val, @@ -219,5 +332,136 @@ pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) return _mm512_reduce_add_epi64(accum); } -#endif /* TRY_POPCNT_X86_64 */ #endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * pg_popcount32_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount32_fast(uint32 word) +{ +#ifdef _MSC_VER + return __popcnt(word); +#else + uint32 res; + +__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount64_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount64_fast(uint64 word) +{ +#ifdef _MSC_VER + return __popcnt64(word); +#else + uint64 res; + +__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount_fast + * Returns the number of 1-bits in buf + */ +static uint64 +pg_popcount_fast(const char *buf, int bytes) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++]; + + return popcnt; +} + +/* + * pg_popcount_masked_fast + * Returns the number of 1-bits in buf after applying the mask to each byte + */ +static uint64 +pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned */ + uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++ & maskv); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + uint32 maskv = ~((uint32) 0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++ & maskv); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; + + return popcnt; +} + +#endif /* TRY_POPCNT_X86_64 */ -- 2.50.1 (Apple Git-155) --KuW0xlRTZoVkcm/J Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-Rename-fast-and-slow-popcount-functions.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v1 2/3] Move x86 popcount code to pg_popcount_x86_64.c. @ 2026-01-14 17:54 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-01-14 17:54 UTC (permalink / raw) This moves the SSE4.2 popcount implementations to the recently renamed file for x86-64-specific popcount code. --- src/include/port/pg_bitutils.h | 20 ++- src/port/pg_bitutils.c | 263 +------------------------------- src/port/pg_popcount_x86_64.c | 264 +++++++++++++++++++++++++++++++-- 3 files changed, 267 insertions(+), 280 deletions(-) diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 8ed12f7a021..c9c508d4ba3 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -307,23 +307,21 @@ pg_ceil_log2_64(uint64 num) #define POPCNT_AARCH64 1 #endif +extern int pg_popcount32_slow(uint32 word); +extern int pg_popcount64_slow(uint64 word); +extern uint64 pg_popcount_slow(const char *buf, int bytes); +extern uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); + #ifdef TRY_POPCNT_X86_64 -/* Attempt to use the POPCNT instruction, but perform a runtime check first */ +/* + * Attempt to use SSE4.2 or AVX-512 instructions, but perform a runtime check + * first. + */ extern PGDLLIMPORT int (*pg_popcount32) (uint32 word); extern PGDLLIMPORT int (*pg_popcount64) (uint64 word); extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes); extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask); -/* - * We can also try to use the AVX-512 popcount instruction on some systems. - * The implementation of that is located in its own file. - */ -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK -extern bool pg_popcount_avx512_available(void); -extern uint64 pg_popcount_avx512(const char *buf, int bytes); -extern uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); -#endif - #elif POPCNT_AARCH64 /* Use the Neon version of pg_popcount{32,64} without function pointer. */ extern int pg_popcount32(uint32 word); diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 7875bbb0f4b..9f9f90ddd4d 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -12,13 +12,6 @@ */ #include "c.h" -#ifdef HAVE__GET_CPUID -#include <cpuid.h> -#endif -#ifdef HAVE__CPUID -#include <intrin.h> -#endif - #include "port/pg_bitutils.h" @@ -103,257 +96,11 @@ const uint8 pg_number_of_ones[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 -static inline int pg_popcount32_slow(uint32 word); -static inline int pg_popcount64_slow(uint64 word); -static uint64 pg_popcount_slow(const char *buf, int bytes); -static uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); -#endif - -#ifdef TRY_POPCNT_X86_64 -static bool pg_popcount_available(void); -static int pg_popcount32_choose(uint32 word); -static int pg_popcount64_choose(uint64 word); -static uint64 pg_popcount_choose(const char *buf, int bytes); -static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); -static inline int pg_popcount32_fast(uint32 word); -static inline int pg_popcount64_fast(uint64 word); -static uint64 pg_popcount_fast(const char *buf, int bytes); -static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); - -int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; -int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; -uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; -uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; -#endif /* TRY_POPCNT_X86_64 */ - -#ifdef TRY_POPCNT_X86_64 - -/* - * Return true if CPUID indicates that the POPCNT instruction is available. - */ -static bool -pg_popcount_available(void) -{ - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID) - __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUID) - __cpuid(exx, 1); -#else -#error cpuid instruction not available -#endif - - return (exx[2] & (1 << 23)) != 0; /* POPCNT */ -} - -/* - * These functions get called on the first call to pg_popcount32 etc. - * They detect whether we can use the asm implementations, and replace - * the function pointers so that subsequent calls are routed directly to - * the chosen implementation. - */ -static inline void -choose_popcount_functions(void) -{ - if (pg_popcount_available()) - { - pg_popcount32 = pg_popcount32_fast; - pg_popcount64 = pg_popcount64_fast; - pg_popcount_optimized = pg_popcount_fast; - pg_popcount_masked_optimized = pg_popcount_masked_fast; - } - else - { - pg_popcount32 = pg_popcount32_slow; - pg_popcount64 = pg_popcount64_slow; - pg_popcount_optimized = pg_popcount_slow; - pg_popcount_masked_optimized = pg_popcount_masked_slow; - } - -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK - if (pg_popcount_avx512_available()) - { - pg_popcount_optimized = pg_popcount_avx512; - pg_popcount_masked_optimized = pg_popcount_masked_avx512; - } -#endif -} - -static int -pg_popcount32_choose(uint32 word) -{ - choose_popcount_functions(); - return pg_popcount32(word); -} - -static int -pg_popcount64_choose(uint64 word) -{ - choose_popcount_functions(); - return pg_popcount64(word); -} - -static uint64 -pg_popcount_choose(const char *buf, int bytes) -{ - choose_popcount_functions(); - return pg_popcount_optimized(buf, bytes); -} - -static uint64 -pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) -{ - choose_popcount_functions(); - return pg_popcount_masked(buf, bytes, mask); -} - -/* - * pg_popcount32_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount32_fast(uint32 word) -{ -#ifdef _MSC_VER - return __popcnt(word); -#else - uint32 res; - -__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount64_fast - * Return the number of 1 bits set in word - */ -static inline int -pg_popcount64_fast(uint64 word) -{ -#ifdef _MSC_VER - return __popcnt64(word); -#else - uint64 res; - -__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); - return (int) res; -#endif -} - -/* - * pg_popcount_fast - * Returns the number of 1-bits in buf - */ -static uint64 -pg_popcount_fast(const char *buf, int bytes) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++]; - - return popcnt; -} - -/* - * pg_popcount_masked_fast - * Returns the number of 1-bits in buf after applying the mask to each byte - */ -static uint64 -pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) -{ - uint64 popcnt = 0; - -#if SIZEOF_VOID_P >= 8 - /* Process in 64-bit chunks if the buffer is aligned */ - uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(8, buf)) - { - const uint64 *words = (const uint64 *) buf; - - while (bytes >= 8) - { - popcnt += pg_popcount64_fast(*words++ & maskv); - bytes -= 8; - } - - buf = (const char *) words; - } -#else - /* Process in 32-bit chunks if the buffer is aligned. */ - uint32 maskv = ~((uint32) 0) / 0xFF * mask; - - if (buf == (const char *) TYPEALIGN(4, buf)) - { - const uint32 *words = (const uint32 *) buf; - - while (bytes >= 4) - { - popcnt += pg_popcount32_fast(*words++ & maskv); - bytes -= 4; - } - - buf = (const char *) words; - } -#endif - - /* Process any remaining bytes */ - while (bytes--) - popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; - - return popcnt; -} - -#endif /* TRY_POPCNT_X86_64 */ - -/* - * If we are building the Neon versions, we don't need the "slow" fallbacks. - */ -#ifndef POPCNT_AARCH64 - /* * pg_popcount32_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount32_slow(uint32 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -375,7 +122,7 @@ pg_popcount32_slow(uint32 word) * pg_popcount64_slow * Return the number of 1 bits set in word */ -static inline int +int pg_popcount64_slow(uint64 word) { #ifdef HAVE__BUILTIN_POPCOUNT @@ -403,7 +150,7 @@ pg_popcount64_slow(uint64 word) * pg_popcount_slow * Returns the number of 1-bits in buf */ -static uint64 +uint64 pg_popcount_slow(const char *buf, int bytes) { uint64 popcnt = 0; @@ -449,7 +196,7 @@ pg_popcount_slow(const char *buf, int bytes) * pg_popcount_masked_slow * Returns the number of 1-bits in buf after applying the mask to each byte */ -static uint64 +uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) { uint64 popcnt = 0; @@ -495,8 +242,6 @@ pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) return popcnt; } -#endif /* ! POPCNT_AARCH64 */ - #if !defined(TRY_POPCNT_X86_64) && !defined(POPCNT_AARCH64) /* diff --git a/src/port/pg_popcount_x86_64.c b/src/port/pg_popcount_x86_64.c index 453c7a06ce9..f8643642613 100644 --- a/src/port/pg_popcount_x86_64.c +++ b/src/port/pg_popcount_x86_64.c @@ -12,26 +12,74 @@ */ #include "c.h" -#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +#include "port/pg_bitutils.h" + +#ifdef TRY_POPCNT_X86_64 #if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) #include <cpuid.h> #endif +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK #include <immintrin.h> +#endif #if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) #include <intrin.h> #endif -#include "port/pg_bitutils.h" +/* + * The SSE4.2 versions are built regardless of whether we are building the + * AVX-512 versions. + */ +static inline int pg_popcount32_fast(uint32 word); +static inline int pg_popcount64_fast(uint64 word); +static uint64 pg_popcount_fast(const char *buf, int bytes); +static uint64 pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask); /* - * It's probably unlikely that TRY_POPCNT_X86_64 won't be set if we are able to - * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on - * the function pointers that are only used when TRY_POPCNT_X86_64 is set. + * These are the AVX-512 implementations of the popcount functions. */ -#ifdef TRY_POPCNT_X86_64 +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK +static uint64 pg_popcount_avx512(const char *buf, int bytes); +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * The function pointers are initially set to "choose" functions. These + * functions will first set the pointers to the right implementations (base on + * what the current CPU supports) and then will call the pointer to fulfill the + * caller's request. + */ +static int pg_popcount32_choose(uint32 word); +static int pg_popcount64_choose(uint64 word); +static uint64 pg_popcount_choose(const char *buf, int bytes); +static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); +int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; +int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; +uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; +uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; + +/* + * Return true if CPUID indicates that the POPCNT instruction is available. + */ +static bool +pg_popcount_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + + return (exx[2] & (1 << 23)) != 0; /* POPCNT */ +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK /* * Does CPUID say there's support for XSAVE instructions? @@ -94,7 +142,7 @@ avx512_popcnt_available(void) * Returns true if the CPU supports the instructions required for the AVX-512 * pg_popcount() implementation. */ -bool +static bool pg_popcount_avx512_available(void) { return xsave_available() && @@ -102,12 +150,77 @@ pg_popcount_avx512_available(void) avx512_popcnt_available(); } +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * These functions get called on the first call to pg_popcount32 etc. + * They detect whether we can use the asm implementations, and replace + * the function pointers so that subsequent calls are routed directly to + * the chosen implementation. + */ +static inline void +choose_popcount_functions(void) +{ + if (pg_popcount_available()) + { + pg_popcount32 = pg_popcount32_fast; + pg_popcount64 = pg_popcount64_fast; + pg_popcount_optimized = pg_popcount_fast; + pg_popcount_masked_optimized = pg_popcount_masked_fast; + } + else + { + pg_popcount32 = pg_popcount32_slow; + pg_popcount64 = pg_popcount64_slow; + pg_popcount_optimized = pg_popcount_slow; + pg_popcount_masked_optimized = pg_popcount_masked_slow; + } + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + if (pg_popcount_avx512_available()) + { + pg_popcount_optimized = pg_popcount_avx512; + pg_popcount_masked_optimized = pg_popcount_masked_avx512; + } +#endif +} + +static int +pg_popcount32_choose(uint32 word) +{ + choose_popcount_functions(); + return pg_popcount32(word); +} + +static int +pg_popcount64_choose(uint64 word) +{ + choose_popcount_functions(); + return pg_popcount64(word); +} + +static uint64 +pg_popcount_choose(const char *buf, int bytes) +{ + choose_popcount_functions(); + return pg_popcount_optimized(buf, bytes); +} + +static uint64 +pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) +{ + choose_popcount_functions(); + return pg_popcount_masked(buf, bytes, mask); +} + +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + /* * pg_popcount_avx512 * Returns the number of 1-bits in buf */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_avx512(const char *buf, int bytes) { __m512i val, @@ -163,7 +276,7 @@ pg_popcount_avx512(const char *buf, int bytes) * Returns the number of 1-bits in buf after applying the mask to each byte */ pg_attribute_target("avx512vpopcntdq,avx512bw") -uint64 +static uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) { __m512i val, @@ -219,5 +332,136 @@ pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) return _mm512_reduce_add_epi64(accum); } -#endif /* TRY_POPCNT_X86_64 */ #endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * pg_popcount32_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount32_fast(uint32 word) +{ +#ifdef _MSC_VER + return __popcnt(word); +#else + uint32 res; + +__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount64_fast + * Return the number of 1 bits set in word + */ +static inline int +pg_popcount64_fast(uint64 word) +{ +#ifdef _MSC_VER + return __popcnt64(word); +#else + uint64 res; + +__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc"); + return (int) res; +#endif +} + +/* + * pg_popcount_fast + * Returns the number of 1-bits in buf + */ +static uint64 +pg_popcount_fast(const char *buf, int bytes) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++]; + + return popcnt; +} + +/* + * pg_popcount_masked_fast + * Returns the number of 1-bits in buf after applying the mask to each byte + */ +static uint64 +pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned */ + uint64 maskv = ~UINT64CONST(0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(8, buf)) + { + const uint64 *words = (const uint64 *) buf; + + while (bytes >= 8) + { + popcnt += pg_popcount64_fast(*words++ & maskv); + bytes -= 8; + } + + buf = (const char *) words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + uint32 maskv = ~((uint32) 0) / 0xFF * mask; + + if (buf == (const char *) TYPEALIGN(4, buf)) + { + const uint32 *words = (const uint32 *) buf; + + while (bytes >= 4) + { + popcnt += pg_popcount32_fast(*words++ & maskv); + bytes -= 4; + } + + buf = (const char *) words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; + + return popcnt; +} + +#endif /* TRY_POPCNT_X86_64 */ -- 2.50.1 (Apple Git-155) --RzZ1MyDExwO9gtVK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v1-0003-Rename-fast-and-slow-popcount-functions.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --CT89ko5pLUrsvFtH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..0813cef2729 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index e1de61f36ee..479557abdcc 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..5a0d2045be5 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --6vzYk1swa63ey9i6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 38ca09b423c..c4ed75211db 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f5c93e611d2..f1e35a6af47 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --2xrO7hiVfr8aWtYg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v4-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +---------------------- src/bin/pg_upgrade/controldata.c | 12 +- src/bin/pg_upgrade/exec.c | 23 ---- src/bin/pg_upgrade/file.c | 164 ------------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 31 +---- src/bin/pg_upgrade/pg_upgrade.h | 29 ----- src/bin/pg_upgrade/relfilenumber.c | 37 +----- src/bin/pg_upgrade/version.c | 127 ------------------- 10 files changed, 16 insertions(+), 577 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..01b354e3c44 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 10) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8188355240f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -602,14 +602,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +628,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +667,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..e5d7920c1b1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --ZcI1PtyEAe3VcVeQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v5-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
* [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 @ 2026-04-17 18:20 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 65+ messages in thread From: Nathan Bossart @ 2026-04-17 18:20 UTC (permalink / raw) --- doc/src/sgml/ref/pgupgrade.sgml | 2 +- src/bin/pg_upgrade/check.c | 157 +------------------- src/bin/pg_upgrade/controldata.c | 98 +----------- src/bin/pg_upgrade/exec.c | 23 --- src/bin/pg_upgrade/file.c | 164 --------------------- src/bin/pg_upgrade/multixact_rewrite.c | 11 +- src/bin/pg_upgrade/pg_upgrade.c | 56 +------ src/bin/pg_upgrade/pg_upgrade.h | 29 ---- src/bin/pg_upgrade/relfilenumber.c | 37 +---- src/bin/pg_upgrade/server.c | 3 +- src/bin/pg_upgrade/t/006_transfer_modes.pl | 20 --- src/bin/pg_upgrade/version.c | 127 ---------------- 12 files changed, 26 insertions(+), 701 deletions(-) diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index cc44983a9a8..e4e8c02e6d6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation </para> <para> - <application>pg_upgrade</application> supports upgrades from 9.2.X and later to the current + <application>pg_upgrade</application> supports upgrades from 10.X and later to the current major release of <productname>PostgreSQL</productname>, including snapshot and beta releases. </para> diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f8f31382835..786c1474829 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -28,7 +28,6 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster); static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_not_null_inheritance(ClusterInfo *cluster); static void check_for_gist_inet_ops(ClusterInfo *cluster); -static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); static void check_for_unicode_update(ClusterInfo *cluster); @@ -128,26 +127,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = ALL_VERSIONS }, - /* - * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which - * previously returned "not enabled" by default and was only functionally - * enabled with a compile-time switch; as of 9.4 "line" has a different - * on-disk representation format. - */ - { - .status = gettext_noop("Checking for incompatible \"line\" data type"), - .report_filename = "tables_using_line.txt", - .base_query = - "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"line\" data type in user tables.\n" - "This data type changed its internal and input/output format\n" - "between your old and new versions so this\n" - "cluster cannot currently be upgraded. You can\n" - "drop the problem columns and restart the upgrade.\n"), - .threshold_version = 903 - }, - /* * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid * pg_enum.oid @@ -209,30 +188,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1500 }, - /* - * It's no longer allowed to create tables or views with "unknown"-type - * columns. We do not complain about views with such columns, because - * they should get silently converted to "text" columns during the DDL - * dump and reload; it seems unlikely to be worth making users do that by - * hand. However, if there's a table with such a column, the DDL reload - * will fail, so we should pre-detect that rather than failing - * mid-upgrade. Worse, if there's a matview with such a column, the DDL - * reload will silently change it to "text" which won't match the on-disk - * storage (which is like "cstring"). So we *must* reject that. - */ - { - .status = gettext_noop("Checking for invalid \"unknown\" user columns"), - .report_filename = "tables_using_unknown.txt", - .base_query = - "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n" - "This data type is no longer allowed in tables, so this cluster\n" - "cannot currently be upgraded. You can drop the problem columns\n" - "and restart the upgrade.\n"), - .threshold_version = 906 - }, - /* * PG 12 changed the 'sql_identifier' type storage to be based on name, * not varchar, which breaks on-disk format for existing data. So we need @@ -255,23 +210,6 @@ static DataTypesUsageChecks data_types_usage_checks[] = .threshold_version = 1100 }, - /* - * JSONB changed its storage format during 9.4 beta, so check for it. - */ - { - .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"), - .report_filename = "tables_using_jsonb.txt", - .base_query = - "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid", - .report_text = - gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n" - "The internal format of \"jsonb\" changed during 9.4 beta so this\n" - "cluster cannot currently be upgraded. You can drop the problem \n" - "columns and restart the upgrade.\n"), - .threshold_version = MANUAL_CHECK, - .version_hook = jsonb_9_4_check_applicable - }, - /* * PG 12 removed types abstime, reltime, tinterval. */ @@ -712,20 +650,6 @@ check_and_dump_old_cluster(void) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1800) check_for_gist_inet_ops(&old_cluster); - /* - * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged - * hash indexes - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - { - if (user_opts.check) - old_9_6_invalidate_hash_indexes(&old_cluster, true); - } - - /* 9.5 and below should not have roles starting with pg_ */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) - check_for_pg_role_prefix(&old_cluster); - /* * While not a check option, we do this now because this is the only time * the old server is running. @@ -772,20 +696,6 @@ check_new_cluster(void) * system boundaries. */ check_hard_link(TRANSFER_MODE_SWAP); - - /* - * There are a few known issues with using --swap to upgrade from - * versions older than 10. For example, the sequence tuple format - * changed in v10, and the visibility map format changed in 9.6. - * While such problems are not insurmountable (and we may have to - * deal with similar problems in the future, anyway), it doesn't - * seem worth the effort to support swap mode for upgrades from - * long-unsupported versions. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) - pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", - "10"); - break; } @@ -831,10 +741,6 @@ issue_warnings_and_set_wal_level(void) */ start_postmaster(&new_cluster, true); - /* Reindex hash indexes for old < 10.0 */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906) - old_9_6_invalidate_hash_indexes(&new_cluster, false); - report_extension_updates(&new_cluster); stop_postmaster(false); @@ -892,9 +798,9 @@ check_cluster_versions(void) * upgrades */ - if (GET_MAJOR_VERSION(old_cluster.major_version) < 902) + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.", - "9.2"); + "10"); /* Only current PG version is supported as a target */ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM)) @@ -1569,12 +1475,10 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_cat(anyarray,anyarray)'" ", 'array_prepend(anyelement,anyarray)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 903) appendPQExpBufferStr(&old_polymorphics, ", 'array_remove(anyarray,anyelement)'" ", 'array_replace(anyarray,anyelement,anyelement)'"); - if (GET_MAJOR_VERSION(cluster->major_version) >= 905) appendPQExpBufferStr(&old_polymorphics, ", 'array_position(anyarray,anyelement)'" ", 'array_position(anyarray,anyelement,integer)'" @@ -1870,63 +1774,6 @@ check_for_gist_inet_ops(ClusterInfo *cluster) check_ok(); } -/* - * check_for_pg_role_prefix() - * - * Versions older than 9.6 should not have any pg_* roles - */ -static void -check_for_pg_role_prefix(ClusterInfo *cluster) -{ - PGresult *res; - PGconn *conn = connectToServer(cluster, "template1"); - int ntups; - int i_roloid; - int i_rolname; - FILE *script = NULL; - char output_path[MAXPGPATH]; - - prep_status("Checking for roles starting with \"pg_\""); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "pg_role_prefix.txt"); - - res = executeQueryOrDie(conn, - "SELECT oid AS roloid, rolname " - "FROM pg_catalog.pg_roles " - "WHERE rolname ~ '^pg_'"); - - ntups = PQntuples(res); - i_roloid = PQfnumber(res, "roloid"); - i_rolname = PQfnumber(res, "rolname"); - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "%s (oid=%s)\n", - PQgetvalue(res, rowno, i_rolname), - PQgetvalue(res, rowno, i_roloid)); - } - - PQclear(res); - - PQfinish(conn); - - if (script) - { - fclose(script); - pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains roles starting with \"pg_\".\n" - "\"pg_\" is a reserved prefix for system roles. The cluster\n" - "cannot be upgraded until these roles are renamed.\n" - "A list of roles starting with \"pg_\" is in the file:\n" - " %s", output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index cffcd4b0eba..8f81c9e9582 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -42,9 +42,6 @@ get_control_data(ClusterInfo *cluster) char bufin[MAX_STRING]; FILE *output; char *p; - bool got_tli = false; - bool got_log_id = false; - bool got_log_seg = false; bool got_xid = false; bool got_oid = false; bool got_multi = false; @@ -75,10 +72,6 @@ get_control_data(ClusterInfo *cluster) char *language = NULL; char *lc_all = NULL; char *lc_messages = NULL; - uint32 tli = 0; - uint32 logid = 0; - uint32 segno = 0; - char *resetwal_bin; int rc; bool live_check = (cluster == &old_cluster && user_opts.live_check); @@ -189,27 +182,15 @@ get_control_data(ClusterInfo *cluster) } } - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - resetwal_bin = "pg_resetxlog\" -n"; - else - resetwal_bin = "pg_resetwal\" -n"; snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"", cluster->bindir, - live_check ? "pg_controldata\"" : resetwal_bin, + live_check ? "pg_controldata\"" : "pg_resetwal\" -n", cluster->pgdata); fflush(NULL); if ((output = popen(cmd, "r")) == NULL) pg_fatal("could not get control data using %s: %m", cmd); - /* Only in <= 9.2 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - cluster->controldata.data_checksum_version = PG_DATA_CHECKSUM_OFF; - got_data_checksum_version = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -237,39 +218,6 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.cat_ver = str2uint(p); } - else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - tli = str2uint(p); - got_tli = true; - } - else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - logid = str2uint(p); - got_log_id = true; - } - else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem", __LINE__); - - p++; /* remove ':' char */ - segno = str2uint(p); - got_log_seg = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL) { p = strchr(p, ':'); @@ -280,23 +228,12 @@ get_control_data(ClusterInfo *cluster) p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtepoch = str2uint(p); - /* - * Delimiter changed from '/' to ':' in 9.6. We don't test for - * the catalog version of the change because the catalog version - * is pulled from pg_controldata too, and it isn't worth adding an - * order dependency for this --- we just check the string. - */ - if (strchr(p, '/') != NULL) - p = strchr(p, '/'); - else if (GET_MAJOR_VERSION(cluster->major_version) >= 906) p = strchr(p, ':'); - else - p = NULL; if (p == NULL || strlen(p) <= 1) pg_fatal("%d: controldata retrieval problem", __LINE__); - p++; /* remove '/' or ':' char */ + p++; /* remove ':' char */ cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } @@ -568,22 +505,6 @@ get_control_data(ClusterInfo *cluster) pg_free(lc_all); pg_free(lc_messages); - /* - * Before 9.3, pg_resetwal reported the xlogid and segno of the first log - * file after reset as separate lines. Starting with 9.3, it reports the - * WAL file name. If the old cluster is older than 9.3, we construct the - * WAL file name from the xlogid and segno. - */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 902) - { - if (got_tli && got_log_id && got_log_seg) - { - snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X", - tli, logid, segno); - got_nextxlogfile = true; - } - } - /* * Pre-v18 database clusters don't have the default char signedness * information. We use the char signedness of the platform where @@ -602,14 +523,12 @@ get_control_data(ClusterInfo *cluster) /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || - (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || + !got_oldestmulti || !got_mxoff || (!live_check && !got_nextxlogfile) || !got_float8_pass_by_value || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || - (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || + !got_large_object || !got_date_is_int || !got_data_checksum_version || (!got_default_char_signedness && cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) @@ -630,8 +549,7 @@ get_control_data(ClusterInfo *cluster) if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId"); - if (!got_oldestmulti && - cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) + if (!got_oldestmulti) pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId"); if (!got_oldestxid) @@ -670,8 +588,7 @@ get_control_data(ClusterInfo *cluster) if (!got_toast) pg_log(PG_REPORT, " maximum TOAST chunk size"); - if (!got_large_object && - cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) + if (!got_large_object) pg_log(PG_REPORT, " large-object chunk size"); if (!got_date_is_int) @@ -724,8 +641,7 @@ check_control_data(ControlData *oldctrl, if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast) pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match"); - /* large_object added in 9.5, so it might not exist in the old cluster */ - if (oldctrl->large_object != 0 && + if (oldctrl->large_object == 0 || oldctrl->large_object != newctrl->large_object) pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match"); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 563b4a6b5fa..44355feea30 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -55,16 +55,7 @@ get_bin_version(ClusterInfo *cluster) if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1) pg_fatal("could not get pg_ctl version output from %s", cmd); - if (v1 < 10) - { - /* old style, e.g. 9.6.1 */ - cluster->bin_version = v1 * 10000 + v2 * 100; - } - else - { - /* new style, e.g. 10.1 */ cluster->bin_version = v1 * 10000; - } } @@ -353,17 +344,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "pg_subtrans"); check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); - - /* pg_xlog has been renamed to pg_wal in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_xlog"); - else check_single_dir(pg_data, "pg_wal"); - - /* pg_clog has been renamed to pg_xact in v10 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 906) - check_single_dir(pg_data, "pg_clog"); - else check_single_dir(pg_data, "pg_xact"); } @@ -404,10 +385,6 @@ check_bin_dir(ClusterInfo *cluster, bool check_versions) */ get_bin_version(cluster); - /* pg_resetxlog has been renamed to pg_resetwal in version 10 */ - if (GET_MAJOR_VERSION(cluster->bin_version) <= 906) - check_exec(cluster->bindir, "pg_resetxlog", check_versions); - else check_exec(cluster->bindir, "pg_resetwal", check_versions); if (cluster == &new_cluster) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 5b276008614..af82c0de490 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -20,12 +20,8 @@ #include <linux/fs.h> #endif -#include "access/visibilitymapdefs.h" #include "common/file_perm.h" #include "pg_upgrade.h" -#include "storage/bufpage.h" -#include "storage/checksum.h" -#include "storage/checksum_impl.h" /* @@ -196,166 +192,6 @@ linkFile(const char *src, const char *dst, } -/* - * rewriteVisibilityMap() - * - * Transform a visibility map file, copying from src to dst. - * schemaName/relName are relation's SQL name (used for error messages only). - * - * In versions of PostgreSQL prior to catversion 201603011, PostgreSQL's - * visibility map included one bit per heap page; it now includes two. - * When upgrading a cluster from before that time to a current PostgreSQL - * version, we could refuse to copy visibility maps from the old cluster - * to the new cluster; the next VACUUM would recreate them, but at the - * price of scanning the entire table. So, instead, we rewrite the old - * visibility maps in the new format. That way, the all-visible bits - * remain set for the pages for which they were set previously. The - * all-frozen bits are never set by this conversion; we leave that to VACUUM. - */ -void -rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName) -{ - int src_fd; - int dst_fd; - PGIOAlignedBlock buffer; - PGIOAlignedBlock new_vmbuf; - ssize_t totalBytesRead = 0; - ssize_t src_filesize; - int rewriteVmBytesPerPage; - BlockNumber new_blkno = 0; - struct stat statbuf; - - /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; - - if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", - schemaName, relName, fromfile); - - if (fstat(src_fd, &statbuf) != 0) - pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m", - schemaName, relName, fromfile); - - if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - pg_file_create_mode)) < 0) - pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m", - schemaName, relName, tofile); - - /* Save old file size */ - src_filesize = statbuf.st_size; - - /* - * Turn each visibility map page into 2 pages one by one. Each new page - * has the same page header as the old one. If the last section of the - * last page is empty, we skip it, mostly to avoid turning one-page - * visibility maps for small relations into two pages needlessly. - */ - while (totalBytesRead < src_filesize) - { - ssize_t bytesRead; - char *old_cur; - char *old_break; - char *old_blkend; - PageHeaderData pageheader; - bool old_lastblk; - - if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ) - { - if (bytesRead < 0) - pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m", - schemaName, relName, fromfile); - else - pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"", - schemaName, relName, fromfile); - } - - totalBytesRead += BLCKSZ; - old_lastblk = (totalBytesRead == src_filesize); - - /* Save the page header data */ - memcpy(&pageheader, buffer.data, SizeOfPageHeaderData); - - /* - * These old_* variables point to old visibility map page. old_cur - * points to current position on old page. old_blkend points to end of - * old block. old_break is the end+1 position on the old page for the - * data that will be transferred to the current new page. - */ - old_cur = buffer.data + SizeOfPageHeaderData; - old_blkend = buffer.data + bytesRead; - old_break = old_cur + rewriteVmBytesPerPage; - - while (old_break <= old_blkend) - { - char *new_cur; - bool empty = true; - bool old_lastpart; - - /* First, copy old page header to new page */ - memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData); - - /* Rewriting the last part of the last old page? */ - old_lastpart = old_lastblk && (old_break == old_blkend); - - new_cur = new_vmbuf.data + SizeOfPageHeaderData; - - /* Process old page bytes one by one, and turn it into new page. */ - while (old_cur < old_break) - { - uint8 byte = *(uint8 *) old_cur; - uint16 new_vmbits = 0; - int i; - - /* Generate new format bits while keeping old information */ - for (i = 0; i < BITS_PER_BYTE; i++) - { - if (byte & (1 << i)) - { - empty = false; - new_vmbits |= - VISIBILITYMAP_ALL_VISIBLE << (BITS_PER_HEAPBLOCK * i); - } - } - - /* Copy new visibility map bytes to new-format page */ - new_cur[0] = (char) (new_vmbits & 0xFF); - new_cur[1] = (char) (new_vmbits >> 8); - - old_cur++; - new_cur += BITS_PER_HEAPBLOCK; - } - - /* If the last part of the last page is empty, skip writing it */ - if (old_lastpart && empty) - break; - - /* Set new checksum for visibility map page, if enabled */ - if (new_cluster.controldata.data_checksum_version != PG_DATA_CHECKSUM_OFF) - ((PageHeader) new_vmbuf.data)->pd_checksum = - pg_checksum_page(new_vmbuf.data, new_blkno); - - errno = 0; - if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", - schemaName, relName, tofile); - } - - /* Advance for next new page */ - old_break += rewriteVmBytesPerPage; - new_blkno++; - } - } - - /* Clean up */ - close(dst_fd); - close(src_fd); -} - void check_file_clone(void) { diff --git a/src/bin/pg_upgrade/multixact_rewrite.c b/src/bin/pg_upgrade/multixact_rewrite.c index 823984ec8f3..c45b3183684 100644 --- a/src/bin/pg_upgrade/multixact_rewrite.c +++ b/src/bin/pg_upgrade/multixact_rewrite.c @@ -25,10 +25,7 @@ static void RecordMultiXactMembers(SlruSegState *members_writer, * 32-bit offsets to the current format. * * Multixids in the range [from_multi, to_multi) are read from the old - * cluster, and written in the new format. An important edge case is that if - * from_multi == to_multi, this initializes the new pg_multixact files in the - * new format without trying to open any old files. (We rely on that when - * upgrading from PostgreSQL version 9.2 or below.) + * cluster, and written in the new format. * * Returns the new nextOffset value; the caller should set it in the new * control file. The new members always start from offset 1, regardless of @@ -42,6 +39,7 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) SlruSegState *members_writer; char dir[MAXPGPATH] = {0}; bool prev_multixid_valid = false; + OldMultiXactReader *old_reader; /* * The range of valid multi XIDs is unchanged by the conversion (they are @@ -63,10 +61,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) * Convert old multixids, if needed, by reading them one-by-one from the * old cluster. */ - if (to_multi != from_multi) - { - OldMultiXactReader *old_reader; - old_reader = AllocOldMultiXactRead(old_cluster.pgdata, old_cluster.controldata.chkpnt_nxtmulti, old_cluster.controldata.chkpnt_nxtmxoff); @@ -113,7 +107,6 @@ rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi) } FreeOldMultiXactReader(old_reader); - } /* Write the final 'next' offset to the last SLRU page */ RecordMultiXactOffset(offsets_writer, to_multi, diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 2127d297bfe..c6af9035665 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -64,7 +64,7 @@ static void prepare_new_cluster(void); static void prepare_new_globals(void); static void create_new_objects(void); static void copy_xact_xlog_xid(void); -static void set_frozenxids(bool minmxid_only); +static void set_frozenxids(void); static void make_outputdirs(char *pgdata); static void setup(char *argv0); static void create_logical_replication_slots(void); @@ -576,7 +576,7 @@ prepare_new_globals(void) /* * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + set_frozenxids(); /* * Now restore global objects (roles and tablespaces). @@ -714,13 +714,6 @@ create_new_objects(void) end_progress_output(); check_ok(); - /* - * We don't have minmxids for databases or relations in pre-9.3 clusters, - * so set those after we have restored the schema. - */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 902) - set_frozenxids(true); - /* update new_cluster info now that we have objects in the databases */ get_db_rel_and_slot_infos(&new_cluster); } @@ -777,10 +770,7 @@ copy_xact_xlog_xid(void) * Copy old commit logs to new data dir. pg_clog has been renamed to * pg_xact in post-10 clusters. */ - copy_subdir_files(GET_MAJOR_VERSION(old_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact", - GET_MAJOR_VERSION(new_cluster.major_version) <= 906 ? - "pg_clog" : "pg_xact"); + copy_subdir_files("pg_xact", "pg_xact"); prep_status("Setting oldest XID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, @@ -809,7 +799,6 @@ copy_xact_xlog_xid(void) check_ok(); /* Copy or convert pg_multixact files */ - Assert(new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER); Assert(new_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER); if (old_cluster.controldata.cat_ver >= MULTIXACTOFFSET_FORMATCHANGE_CAT_VER) { @@ -844,25 +833,7 @@ copy_xact_xlog_xid(void) * Determine the range of multixacts to convert. */ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; - if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) - { - /* Versions 9.3 - 18: convert all multixids */ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti; - } - else - { - /* - * In PostgreSQL 9.2 and below, multitransactions were only used - * for row locking, and as such don't need to be preserved during - * upgrade. In that case, we utilize rewrite_multixacts() just to - * initialize new, empty files in the new format. - * - * It's important that the oldest multi is set to the latest value - * used by the old system, so that multixact.c returns the empty - * set for multis that might be present on disk. - */ - oldstMulti = nxtmulti; - } /* handle wraparound */ if (nxtmulti < FirstMultiXactId) nxtmulti = FirstMultiXactId; @@ -906,26 +877,18 @@ copy_xact_xlog_xid(void) /* * set_frozenxids() * - * This is called on the new cluster before we restore anything, with - * minmxid_only = false. Its purpose is to ensure that all initdb-created + * This is called on the new cluster before we restore anything. + * Its purpose is to ensure that all initdb-created * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the * built-in databases to match. * * As we create user tables later, their relfrozenxid/relminmxid fields will * be restored properly by the binary-upgrade restore script. Likewise for - * user-database datfrozenxid/datminmxid. However, if we're upgrading from a - * pre-9.3 database, which does not store per-table or per-DB minmxid, then - * the relminmxid/datminmxid values filled in by the restore script will just - * be zeroes. - * - * Hence, with a pre-9.3 source database, a second call occurs after - * everything is restored, with minmxid_only = true. This pass will - * initialize all tables and databases, both those made by initdb and user - * objects, with the desired minmxid value. frozenxid values are left alone. + * user-database datfrozenxid/datminmxid. */ static void -set_frozenxids(bool minmxid_only) +set_frozenxids(void) { int dbnum; PGconn *conn, @@ -935,14 +898,10 @@ set_frozenxids(bool minmxid_only) int i_datname; int i_datallowconn; - if (!minmxid_only) prep_status("Setting frozenxid and minmxid counters in new cluster"); - else - prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - if (!minmxid_only) /* set pg_database.datfrozenxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " @@ -983,7 +942,6 @@ set_frozenxids(bool minmxid_only) conn = connectToServer(&new_cluster, datname); - if (!minmxid_only) /* set pg_class.relfrozenxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index ccd1ac0d013..d6e5bca5792 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -101,19 +101,6 @@ extern char *output_files[]; #endif -/* - * The format of visibility map was changed with this 9.6 commit. - */ -#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER 201603011 - -/* - * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85, - * ("Improve concurrency of foreign key locking") which also updated catalog - * version to this value. pg_upgrade behavior depends on whether old and new - * server versions are both newer than this, or only the new one is. - */ -#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231 - /* * MultiXactOffset was changed from 32-bit to 64-bit in version 19, at this * catalog version. pg_multixact files need to be converted when upgrading @@ -121,17 +108,6 @@ extern char *output_files[]; */ #define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER 202512091 -/* - * large object chunk size added to pg_controldata, - * commit 5f93c37805e7485488480916b4585e098d3cc883 - */ -#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942 - -/* - * change in JSONB format during 9.4 beta - */ -#define JSONB_FORMAT_CHANGE_CAT_VER 201409291 - /* * The control file was changed to have the default char signedness, * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 @@ -429,8 +405,6 @@ void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); -void rewriteVisibilityMap(const char *fromfile, const char *tofile, - const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); void check_hard_link(transferMode transfer_mode); @@ -500,10 +474,7 @@ unsigned int str2uint(const char *str); /* version.c */ -bool jsonb_9_4_check_applicable(ClusterInfo *cluster); bool protocol_negotiation_supported(const ClusterInfo *cluster); -void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, - bool check_mode); void report_extension_updates(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index d5088447e0d..ec2ff7acb21 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -18,7 +18,7 @@ #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace); -static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +static void transfer_relfile(FileNameMap *map, const char *type_suffix); /* * The following set of sync_queue_* functions are used for --swap to reduce @@ -496,25 +496,10 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace) { int mapnum; - bool vm_must_add_frozenbit = false; - - /* - * Do we need to rewrite visibilitymap? - */ - if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER && - new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) - vm_must_add_frozenbit = true; /* --swap has its own subroutine */ if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) { - /* - * We don't support --swap to upgrade from versions that require - * rewriting the visibility map. We should've failed already if - * someone tries to do that. - */ - Assert(!vm_must_add_frozenbit); - do_swap(maps, size, old_tablespace, new_tablespace); return; } @@ -525,13 +510,13 @@ transfer_single_new_db(FileNameMap *maps, int size, strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0) { /* transfer primary file */ - transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], ""); /* * Copy/link any fsm and vm files, if they exist */ - transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit); - transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit); + transfer_relfile(&maps[mapnum], "_fsm"); + transfer_relfile(&maps[mapnum], "_vm"); } } } @@ -540,12 +525,10 @@ transfer_single_new_db(FileNameMap *maps, int size, /* * transfer_relfile() * - * Copy or link file from old cluster to new one. If vm_must_add_frozenbit - * is true, visibility map forks are converted and rewritten, even in link - * mode. + * Copy or link file from old cluster to new one. */ static void -transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit) +transfer_relfile(FileNameMap *map, const char *type_suffix) { char old_file[MAXPGPATH]; char new_file[MAXPGPATH]; @@ -604,14 +587,6 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro /* Copying files might take some time, so give feedback. */ pg_log(PG_STATUS, "%s", old_file); - if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0) - { - /* Need to rewrite visibility map format */ - pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"", - old_file, new_file); - rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname); - } - else switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 5d81e4e95b8..7da9dffe585 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -186,8 +186,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) snprintf(socket_string + strlen(socket_string), sizeof(socket_string) - strlen(socket_string), " -c %s='%s'", - (GET_MAJOR_VERSION(cluster->major_version) <= 902) ? - "unix_socket_directory" : "unix_socket_directories", + "unix_socket_directories", cluster->sockdir); #endif diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl index 6b7ab9f29a2..9efa5dc863c 100644 --- a/src/bin/pg_upgrade/t/006_transfer_modes.pl +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -17,15 +17,6 @@ sub test_mode PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); my $new = PostgreSQL::Test::Cluster->new('new'); - # --swap can't be used to upgrade from versions older than 10, so just skip - # the test if the old cluster version is too old. - if ($old->pg_version < 10 && $mode eq "--swap") - { - $old->clean_node(); - $new->clean_node(); - return; - } - if (defined($ENV{oldinstall})) { # Checksums are now enabled by default, but weren't before 18, so pass @@ -38,14 +29,10 @@ sub test_mode } $new->init(); - # allow_in_place_tablespaces is available as far back as v10. - if ($old->pg_version >= 10) - { $new->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); $old->append_conf('postgresql.conf', "allow_in_place_tablespaces = true"); - } # We can only test security labels if both the old and new installations # have dummy_seclabel. @@ -89,9 +76,6 @@ sub test_mode "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); } - # If the old cluster is >= v10, we can test in-place tablespaces. - if ($old->pg_version >= 10) - { $old->safe_psql('postgres', "CREATE TABLESPACE inplc_tblspc LOCATION ''"); $old->safe_psql('postgres', @@ -101,7 +85,6 @@ sub test_mode ); $old->safe_psql('testdb3', "CREATE TABLE test6 AS SELECT generate_series(607, 711)"); - } # While we are here, test handling of large objects. $old->safe_psql( @@ -169,15 +152,12 @@ sub test_mode } # Tests for in-place tablespaces. - if ($old->pg_version >= 10) - { $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test5"); is($result, '104', "test5 data after pg_upgrade $mode"); $result = $new->safe_psql('testdb3', "SELECT COUNT(*) FROM test6"); is($result, '105', "test6 data after pg_upgrade $mode"); - } # Tests for large objects $result = $new->safe_psql('postgres', "SELECT lo_get(4532)"); diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 047670d4acb..9e83d4659be 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -12,22 +12,6 @@ #include "fe_utils/string_utils.h" #include "pg_upgrade.h" -/* - * version_hook functions for check_for_data_types_usage in order to determine - * whether a data type check should be executed for the cluster in question or - * not. - */ -bool -jsonb_9_4_check_applicable(ClusterInfo *cluster) -{ - /* JSONB changed its storage format during 9.4 beta */ - if (GET_MAJOR_VERSION(cluster->major_version) == 904 && - cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) - return true; - - return false; -} - /* * Older servers can't support newer protocol versions, so their connection * strings will need to lock max_protocol_version to 3.0. @@ -46,117 +30,6 @@ protocol_negotiation_supported(const ClusterInfo *cluster) return (GET_MAJOR_VERSION(cluster->major_version) >= 1100); } -/* - * old_9_6_invalidate_hash_indexes() - * 9.6 -> 10 - * Hash index binary format has changed from 9.6->10.0 - */ -void -old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) -{ - int dbnum; - FILE *script = NULL; - bool found = false; - char *output_path = "reindex_hash.sql"; - - prep_status("Checking for hash indexes"); - - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find hash indexes */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_index i, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'" - ); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - found = true; - if (!check_mode) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "REINDEX INDEX %s.%s;\n", - quote_identifier(PQgetvalue(res, rowno, i_nspname)), - quote_identifier(PQgetvalue(res, rowno, i_relname))); - } - } - - PQclear(res); - - if (!check_mode && db_used) - { - /* mark hash indexes as invalid */ - PQclear(executeQueryOrDie(conn, - "UPDATE pg_catalog.pg_index i " - "SET indisvalid = false " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_am a, " - " pg_catalog.pg_namespace n " - "WHERE i.indexrelid = c.oid AND " - " c.relam = a.oid AND " - " c.relnamespace = n.oid AND " - " a.amname = 'hash'")); - } - - PQfinish(conn); - } - - if (script) - fclose(script); - - if (found) - { - report_status(PG_WARNING, "warning"); - if (check_mode) - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. After upgrading, you will be given\n" - "REINDEX instructions."); - else - pg_log(PG_WARNING, "\n" - "Your installation contains hash indexes. These indexes have different\n" - "internal formats between your old and new clusters, so they must be\n" - "reindexed with the REINDEX command. The file\n" - " %s\n" - "when executed by psql by the database superuser will recreate all invalid\n" - "indexes; until then, none of these indexes will be used.", - output_path); - } - else - check_ok(); -} - /* * Callback function for processing results of query for * report_extension_updates()'s UpgradeTask. If the query returned any rows, -- 2.50.1 (Apple Git-155) --aHl3HfeiUuO3zeNC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v6-0003-psql-bump-minimum-supported-version-to-v10.patch ^ permalink raw reply [nested|flat] 65+ messages in thread
end of thread, other threads:[~2026-04-17 18:20 UTC | newest] Thread overview: 65+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2019-08-02 22:59 [PATCH 3/3] Avoid GIN full scan for non-empty ALL keys Nikita Glukhov <[email protected]> 2023-08-07 23:51 [PATCH v1 7/9] regress: Check for postgres startup completion more often Andres Freund <[email protected]> 2023-08-07 23:51 [PATCH v1 7/9] regress: Check for postgres startup completion more often Andres Freund <[email protected]> 2023-08-07 23:51 [PATCH v1 7/9] regress: Check for postgres startup completion more often Andres Freund <[email protected]> 2023-08-07 23:51 [PATCH v3 10/10] regress: Check for postgres startup completion more often Andres Freund <[email protected]> 2023-08-07 23:51 [PATCH v3 10/10] regress: Check for postgres startup completion more often Andres Freund <[email protected]> 2026-01-14 17:54 [PATCH v1 2/3] Move x86 popcount code to pg_popcount_x86_64.c. Nathan Bossart <[email protected]> 2026-01-14 17:54 [PATCH v1 2/3] Move x86 popcount code to pg_popcount_x86_64.c. Nathan Bossart <[email protected]> 2026-01-14 17:54 [PATCH v2 2/4] Move x86 popcount code to pg_popcount_x86_64.c. Nathan Bossart <[email protected]> 2026-01-14 17:54 [PATCH v2 2/4] Move x86 popcount code to pg_popcount_x86_64.c. Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v5 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v6 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v2 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v3 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]> 2026-04-17 18:20 [PATCH v4 2/4] pg_upgrade: bump minimum supported version to v10 Nathan Bossart <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox