On Thu, Jul  3, 2014 at 05:09:41PM -0400, Tom Lane wrote:
> Bruce Momjian <br...@momjian.us> writes:
> > I have had trouble getting a table schema that is causing problems, but
> > received a report via EDB support recently that had a simple schema
> > (anonymized):
> > ...
> > needs_toast_table() computes the length of this table as 2024 bytes in
> > 9.0, and 2064 bytes on 9.1, with the TOAST threshold being 2032 bytes. 
> 
> > My initial idea is to to allow for toast tables in the new cluster that
> > aren't in the old cluster by skipping over the extra toast tables.  This
> > would only be for pre-9.1 old clusters.
> 
> TBH, it has never been more than the shakiest of assumptions that the new
> version could not create toast tables where the old one hadn't.  I think
> you should just allow for that case, independently of specific PG
> versions.  Fortunately it seems easy enough, since you certainly don't
> need to put any data into the new toast tables.

OK, patch attached.

-- 
  Bruce Momjian  <br...@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + Everyone has their own god. +
diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
new file mode 100644
index 6205c74..17e4d5b
*** a/contrib/pg_upgrade/info.c
--- b/contrib/pg_upgrade/info.c
*************** gen_db_file_maps(DbInfo *old_db, DbInfo
*** 38,58 ****
  				 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_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
--- 38,85 ----
  				 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 = &old_db->rel_arr.rels[old_relnum];
! 		RelInfo    *new_rel = &new_db->rel_arr.rels[new_relnum];
! 
  
  		if (old_rel->reloid != new_rel->reloid)
! 		{
! 			if (strcmp(new_rel->nspname, "pg_toast") == 0)
! 				/*
! 				 * 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.
! 				 */
! 				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
*************** gen_db_file_maps(DbInfo *old_db, DbInfo
*** 76,89 ****
  		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_fatal("old and new databases \"%s\" have a different number of relations\n",
  				 old_db->db_name);
  
  	*nmaps = num_maps;
--- 103,114 ----
  		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;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to