Skip to content

Commit 3088cc3

Browse files
committed
pg_upgrade: allow upgrades for new-only TOAST tables
Previously, when calculations on the need for toast tables changed, pg_upgrade could not handle cases where the new cluster needed a TOAST table and the old cluster did not. (It already handled the opposite case.) This fixes the "OID mismatch" error typically generated in this case. Backpatch through 9.2
1 parent 4cbd128 commit 3088cc3

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

contrib/pg_upgrade/info.c

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,61 @@ gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
3838
int *nmaps, const char *old_pgdata, const char *new_pgdata)
3939
{
4040
FileNameMap *maps;
41-
int relnum;
41+
int old_relnum, new_relnum;
4242
int num_maps = 0;
4343

4444
maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) *
4545
old_db->rel_arr.nrels);
4646

47-
for (relnum = 0; relnum < Min(old_db->rel_arr.nrels, new_db->rel_arr.nrels);
48-
relnum++)
47+
/*
48+
* The old database shouldn't have more relations than the new one.
49+
* We force the new cluster to have a TOAST table if the old table
50+
* had one.
51+
*/
52+
if (old_db->rel_arr.nrels > new_db->rel_arr.nrels)
53+
pg_fatal("old and new databases \"%s\" have a mismatched number of relations\n",
54+
old_db->db_name);
55+
56+
/* Drive the loop using new_relnum, which might be higher. */
57+
for (old_relnum = new_relnum = 0; new_relnum < new_db->rel_arr.nrels;
58+
new_relnum++)
4959
{
50-
RelInfo *old_rel = &old_db->rel_arr.rels[relnum];
51-
RelInfo *new_rel = &new_db->rel_arr.rels[relnum];
60+
RelInfo *old_rel;
61+
RelInfo *new_rel = &new_db->rel_arr.rels[new_relnum];
62+
63+
/*
64+
* It is possible that the new cluster has a TOAST table for a table
65+
* that didn't need one in the old cluster, e.g. 9.0 to 9.1 changed the
66+
* NUMERIC length computation. Therefore, if we have a TOAST table
67+
* in the new cluster that doesn't match, skip over it and continue
68+
* processing. It is possible this TOAST table used an OID that was
69+
* reserved in the old cluster, but we have no way of testing that,
70+
* and we would have already gotten an error at the new cluster schema
71+
* creation stage. Fortunately, since we only restore the OID counter
72+
* after schema restore, and restore in OID order via pg_dump, a
73+
* conflict would only happen if the new TOAST table had a very low
74+
* OID. However, TOAST tables created long after initial table
75+
* creation can have any OID, particularly after OID wraparound.
76+
*/
77+
if (old_relnum == old_db->rel_arr.nrels)
78+
{
79+
if (strcmp(new_rel->nspname, "pg_toast") == 0)
80+
continue;
81+
else
82+
pg_fatal("Extra non-TOAST relation found in database \"%s\": new OID %d\n",
83+
old_db->db_name, new_rel->reloid);
84+
}
85+
86+
old_rel = &old_db->rel_arr.rels[old_relnum];
5287

5388
if (old_rel->reloid != new_rel->reloid)
54-
pg_fatal("Mismatch of relation OID in database \"%s\": old OID %d, new OID %d\n",
55-
old_db->db_name, old_rel->reloid, new_rel->reloid);
89+
{
90+
if (strcmp(new_rel->nspname, "pg_toast") == 0)
91+
continue;
92+
else
93+
pg_fatal("Mismatch of relation OID in database \"%s\": old OID %d, new OID %d\n",
94+
old_db->db_name, old_rel->reloid, new_rel->reloid);
95+
}
5696

5797
/*
5898
* TOAST table names initially match the heap pg_class oid. In
@@ -76,14 +116,12 @@ gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
76116
create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db,
77117
old_rel, new_rel, maps + num_maps);
78118
num_maps++;
119+
old_relnum++;
79120
}
80121

81-
/*
82-
* Do this check after the loop so hopefully we will produce a clearer
83-
* error above
84-
*/
85-
if (old_db->rel_arr.nrels != new_db->rel_arr.nrels)
86-
pg_fatal("old and new databases \"%s\" have a different number of relations\n",
122+
/* Did we fail to exhaust the old array? */
123+
if (old_relnum != old_db->rel_arr.nrels)
124+
pg_fatal("old and new databases \"%s\" have a mismatched number of relations\n",
87125
old_db->db_name);
88126

89127
*nmaps = num_maps;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy