Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f64fe2c

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 d54712e commit f64fe2c

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

contrib/pg_upgrade/info.c

+51-13
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)