/* * gen_db_file_maps() * * generates database mappings for "old_db" and "new_db". Returns a malloc'ed * array of mappings. nmaps is a return parameter which refers to the number * mappings. */ FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata) { FileNameMap *maps; int relnum; int num_maps = 0; maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) * old_db->rel_arr.nrels); for (relnum = 0; relnum < Min(old_db->rel_arr.nrels, new_db->rel_arr.nrels); relnum++) { RelInfo *old_rel = &old_db->rel_arr.rels[relnum]; RelInfo *new_rel = &new_db->rel_arr.rels[relnum]; if (old_rel->reloid != new_rel->reloid) pg_log(PG_FATAL, "Mismatch of relation OID in database \"%s\": old OID %d, new OID %d\n", old_db->db_name, old_rel->reloid, new_rel->reloid); /* * TOAST table names initially match the heap pg_class oid. In * pre-8.4, TOAST table names change during CLUSTER; in pre-9.0, TOAST * table names change during ALTER TABLE ALTER COLUMN SET TYPE. In >= * 9.0, TOAST relation names always use heap table oids, hence we * cannot check relation names when upgrading from pre-9.0. Clusters * upgraded to 9.0 will get matching TOAST names. If index names don't * match primary key constraint names, this will fail because pg_dump * dumps constraint names and pg_upgrade checks index names. */ if (strcmp(old_rel->nspname, new_rel->nspname) != 0 || ((GET_MAJOR_VERSION(old_cluster.major_version) >= 900 || strcmp(old_rel->nspname, "pg_toast") != 0) && strcmp(old_rel->relname, new_rel->relname) != 0)) pg_log(PG_FATAL, "Mismatch of relation names in database \"%s\": " "old name \"%s.%s\", new name \"%s.%s\"\n", old_db->db_name, old_rel->nspname, old_rel->relname, new_rel->nspname, new_rel->relname); create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db, old_rel, new_rel, maps + num_maps); num_maps++; } /* * Do this check after the loop so hopefully we will produce a clearer * error above */ if (old_db->rel_arr.nrels != new_db->rel_arr.nrels) pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n", old_db->db_name); *nmaps = num_maps; return maps; }
/* * gen_db_file_maps() * * generates database mappings for "old_db" and "new_db". Returns a malloc'ed * array of mappings. nmaps is a return parameter which refers to the number * mappings. */ FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata) { FileNameMap *maps; int relnum; int num_maps = 0; if (old_db->rel_arr.nrels != new_db->rel_arr.nrels) pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n", old_db->db_name); maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) * old_db->rel_arr.nrels); for (relnum = 0; relnum < old_db->rel_arr.nrels; relnum++) { RelInfo *old_rel = &old_db->rel_arr.rels[relnum]; RelInfo *new_rel = &new_db->rel_arr.rels[relnum]; if (old_rel->reloid != new_rel->reloid) pg_log(PG_FATAL, "Mismatch of relation id: database \"%s\", old relid %d, new relid %d\n", old_db->db_name, old_rel->reloid, new_rel->reloid); /* * TOAST table names initially match the heap pg_class oid. * In pre-8.4, TOAST table names change during CLUSTER; in pre-9.0, * TOAST table names change during ALTER TABLE ALTER COLUMN SET TYPE. * In >= 9.0, TOAST relation names always use heap table oids, hence * we cannot check relation names when upgrading from pre-9.0. * Clusters upgraded to 9.0 will get matching TOAST names. */ if (strcmp(old_rel->nspname, new_rel->nspname) != 0 || ((GET_MAJOR_VERSION(old_cluster.major_version) >= 900 || strcmp(old_rel->nspname, "pg_toast") != 0) && strcmp(old_rel->relname, new_rel->relname) != 0)) pg_log(PG_FATAL, "Mismatch of relation names: database \"%s\", " "old rel %s.%s, new rel %s.%s\n", old_db->db_name, old_rel->nspname, old_rel->relname, new_rel->nspname, new_rel->relname); create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db, old_rel, new_rel, maps + num_maps); num_maps++; } *nmaps = num_maps; return maps; }
/* * gen_db_file_maps() * * generates database mappings for "old_db" and "new_db". Returns a malloc'ed * array of mappings. nmaps is a return parameter which refers to the number * mappings. */ FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata) { FileNameMap *maps; int old_relnum, new_relnum; int num_maps = 0; maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) * old_db->rel_arr.nrels); /* * The old database shouldn't have more relations than the new one. * We force the new cluster to have a TOAST table if the old table * had one. */ if (old_db->rel_arr.nrels > new_db->rel_arr.nrels) pg_fatal("old and new databases \"%s\" have a mismatched number of relations\n", old_db->db_name); /* Drive the loop using new_relnum, which might be higher. */ for (old_relnum = new_relnum = 0; new_relnum < new_db->rel_arr.nrels; new_relnum++) { RelInfo *old_rel; RelInfo *new_rel = &new_db->rel_arr.rels[new_relnum]; /* * It is possible that the new cluster has a TOAST table for a table * that didn't need one in the old cluster, e.g. 9.0 to 9.1 changed the * NUMERIC length computation. Therefore, if we have a TOAST table * in the new cluster that doesn't match, skip over it and continue * processing. It is possible this TOAST table used an OID that was * reserved in the old cluster, but we have no way of testing that, * and we would have already gotten an error at the new cluster schema * creation stage. Fortunately, since we only restore the OID counter * after schema restore, and restore in OID order via pg_dump, a * conflict would only happen if the new TOAST table had a very low * OID. However, TOAST tables created long after initial table * creation can have any OID, particularly after OID wraparound. */ if (old_relnum == old_db->rel_arr.nrels) { if (strcmp(new_rel->nspname, "pg_toast") == 0) continue; else pg_fatal("Extra non-TOAST relation found in database \"%s\": new OID %d\n", old_db->db_name, new_rel->reloid); } old_rel = &old_db->rel_arr.rels[old_relnum]; if (old_rel->reloid != new_rel->reloid) { if (strcmp(new_rel->nspname, "pg_toast") == 0) continue; else pg_fatal("Mismatch of relation OID in database \"%s\": old OID %d, new OID %d\n", old_db->db_name, old_rel->reloid, new_rel->reloid); } /* * TOAST table names initially match the heap pg_class oid. In * pre-8.4, TOAST table names change during CLUSTER; in pre-9.0, TOAST * table names change during ALTER TABLE ALTER COLUMN SET TYPE. In >= * 9.0, TOAST relation names always use heap table oids, hence we * cannot check relation names when upgrading from pre-9.0. Clusters * upgraded to 9.0 will get matching TOAST names. If index names don't * match primary key constraint names, this will fail because pg_dump * dumps constraint names and pg_upgrade checks index names. */ if (strcmp(old_rel->nspname, new_rel->nspname) != 0 || ((GET_MAJOR_VERSION(old_cluster.major_version) >= 900 || strcmp(old_rel->nspname, "pg_toast") != 0) && strcmp(old_rel->relname, new_rel->relname) != 0)) pg_fatal("Mismatch of relation names in database \"%s\": " "old name \"%s.%s\", new name \"%s.%s\"\n", old_db->db_name, old_rel->nspname, old_rel->relname, new_rel->nspname, new_rel->relname); create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db, old_rel, new_rel, maps + num_maps); num_maps++; old_relnum++; } /* Did we fail to exhaust the old array? */ if (old_relnum != old_db->rel_arr.nrels) pg_fatal("old and new databases \"%s\" have a mismatched number of relations\n", old_db->db_name); *nmaps = num_maps; return maps; }
/* * gen_db_file_maps() * * generates a database mapping from "old_db" to "new_db". * * Returns a malloc'ed array of mappings. The length of the array * is returned into *nmaps. */ FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata) { FileNameMap *maps; int old_relnum, new_relnum; int num_maps = 0; bool all_matched = true; /* There will certainly not be more mappings than there are old rels */ maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) * old_db->rel_arr.nrels); /* * Each of the RelInfo arrays should be sorted by OID. Scan through them * and match them up. If we fail to match everything, we'll abort, but * first print as much info as we can about mismatches. */ old_relnum = new_relnum = 0; while (old_relnum < old_db->rel_arr.nrels || new_relnum < new_db->rel_arr.nrels) { RelInfo *old_rel = (old_relnum < old_db->rel_arr.nrels) ? &old_db->rel_arr.rels[old_relnum] : NULL; RelInfo *new_rel = (new_relnum < new_db->rel_arr.nrels) ? &new_db->rel_arr.rels[new_relnum] : NULL; /* handle running off one array before the other */ if (!new_rel) { /* * old_rel is unmatched. This should never happen, because we * force new rels to have TOAST tables if the old one did. */ report_unmatched_relation(old_rel, old_db, false); all_matched = false; old_relnum++; continue; } if (!old_rel) { /* * new_rel is unmatched. This shouldn't really happen either, but * if it's a TOAST table, we can ignore it and continue * processing, assuming that the new server made a TOAST table * that wasn't needed. */ if (strcmp(new_rel->nspname, "pg_toast") != 0) { report_unmatched_relation(new_rel, new_db, true); all_matched = false; } new_relnum++; continue; } /* check for mismatched OID */ if (old_rel->reloid < new_rel->reloid) { /* old_rel is unmatched, see comment above */ report_unmatched_relation(old_rel, old_db, false); all_matched = false; old_relnum++; continue; } else if (old_rel->reloid > new_rel->reloid) { /* new_rel is unmatched, see comment above */ if (strcmp(new_rel->nspname, "pg_toast") != 0) { report_unmatched_relation(new_rel, new_db, true); all_matched = false; } new_relnum++; continue; } /* * Verify that rels of same OID have same name. The namespace name * should always match, but the relname might not match for TOAST * tables (and, therefore, their indexes). * * TOAST table names initially match the heap pg_class oid, but * pre-9.0 they can change during certain commands such as CLUSTER, so * don't insist on a match if old cluster is < 9.0. */ if (strcmp(old_rel->nspname, new_rel->nspname) != 0 || (strcmp(old_rel->relname, new_rel->relname) != 0 && (GET_MAJOR_VERSION(old_cluster.major_version) >= 900 || strcmp(old_rel->nspname, "pg_toast") != 0))) { pg_log(PG_WARNING, "Relation names for OID %u in database \"%s\" do not match: " "old name \"%s.%s\", new name \"%s.%s\"\n", old_rel->reloid, old_db->db_name, old_rel->nspname, old_rel->relname, new_rel->nspname, new_rel->relname); all_matched = false; old_relnum++; new_relnum++; continue; } /* OK, create a mapping entry */ create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db, old_rel, new_rel, maps + num_maps); num_maps++; old_relnum++; new_relnum++; } if (!all_matched) pg_fatal("Failed to match up old and new tables in database \"%s\"\n", old_db->db_name); *nmaps = num_maps; return maps; }