Skip to content

Commit 759c9fb

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 981518e commit 759c9fb

File tree

1 file changed

+51
-10
lines changed

1 file changed

+51
-10
lines changed

contrib/pg_upgrade/info.c

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

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

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

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

5696
/*
5797
* TOAST table names initially match the heap pg_class oid. In
@@ -73,11 +113,12 @@ gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
73113
create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db,
74114
old_rel, new_rel, maps + num_maps);
75115
num_maps++;
116+
old_relnum++;
76117
}
77118

78-
/* Do this check after the loop so hopefully we will produce a clearer error above */
79-
if (old_db->rel_arr.nrels != new_db->rel_arr.nrels)
80-
pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n",
119+
/* Did we fail to exhaust the old array? */
120+
if (old_relnum != old_db->rel_arr.nrels)
121+
pg_log(PG_FATAL, "old and new databases \"%s\" have a mismatched number of relations\n",
81122
old_db->db_name);
82123

83124
*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