Example #1
0
/*
 * 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;
}
Example #2
0
/*
 * 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;
}
Example #3
0
File: info.c Project: no0p/postgres
/*
 * 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;
}
Example #4
0
/*
 * 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;
}