@@ -37,21 +37,61 @@ gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
3737int * nmaps ,const char * old_pgdata ,const char * new_pgdata )
3838{
3939FileNameMap * maps ;
40- int relnum ;
40+ int old_relnum , new_relnum ;
4141int num_maps = 0 ;
4242
4343maps = (FileNameMap * )pg_malloc (sizeof (FileNameMap )*
4444old_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
5287if (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,
73113create_rel_filename_map (old_pgdata ,new_pgdata ,old_db ,new_db ,
74114old_rel ,new_rel ,maps + num_maps );
75115num_maps ++ ;
116+ old_relnum ++ ;
76117}
77118
78- /*Do this check after the loop so hopefully wewill 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 adifferent number of relations\n" ,
119+ /*Did wefail 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 amismatched number of relations\n" ,
81122old_db -> db_name );
82123
83124* nmaps = num_maps ;