pg_upgrade: Preserve relfilenodes and tablespace OIDs.

Currently, database OIDs, relfilenodes, and tablespace OIDs can all
change when a cluster is upgraded using pg_upgrade. It seems better
to preserve them, because (1) it makes troubleshooting pg_upgrade
easier, since you don't have to do a lot of work to match up files
in the old and new clusters, (2) it allows 'rsync' to save bandwidth
when used to re-sync a cluster after an upgrade, and (3) if we ever
encrypt or sign blocks, we would likely want to use a nonce that
depends on these values.

This patch only arranges to preserve relfilenodes and tablespace
OIDs. The task of preserving database OIDs is left for another patch,
since it involves some complexities that don't exist in these cases.

Database OIDs have a similar issue, but there are some tricky points
in that case that do not apply to these cases, so that problem is left
for another patch.

Shruthi KC, based on an earlier patch from Antonin Houska, reviewed
and with some adjustments by me.

Discussion: http://postgr.es/m/CA+TgmoYgTwYcUmB=e8+hRHOFA0kkS6Kde85+UNdon6q7bt1niQ@mail.gmail.com
This commit is contained in:
Robert Haas 2022-01-17 13:32:44 -05:00
parent 2131c049d3
commit 9a974cbcba
16 changed files with 247 additions and 108 deletions

View File

@ -212,7 +212,8 @@ Boot_CreateStmt:
mapped_relation, mapped_relation,
true, true,
&relfrozenxid, &relfrozenxid,
&relminmxid); &relminmxid,
true);
elog(DEBUG4, "bootstrap relation created"); elog(DEBUG4, "bootstrap relation created");
} }
else else

View File

@ -91,7 +91,9 @@
/* Potentially set by pg_upgrade_support functions */ /* Potentially set by pg_upgrade_support functions */
Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid; Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid;
Oid binary_upgrade_next_heap_pg_class_relfilenode = InvalidOid;
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid; Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid;
Oid binary_upgrade_next_toast_pg_class_relfilenode = InvalidOid;
static void AddNewRelationTuple(Relation pg_class_desc, static void AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc, Relation new_rel_desc,
@ -285,8 +287,12 @@ SystemAttributeByName(const char *attname)
* heap_create - Create an uncataloged heap relation * heap_create - Create an uncataloged heap relation
* *
* Note API change: the caller must now always provide the OID * Note API change: the caller must now always provide the OID
* to use for the relation. The relfilenode may (and, normally, * to use for the relation. The relfilenode may be (and in
* should) be left unspecified. * the simplest cases is) left unspecified.
*
* create_storage indicates whether or not to create the storage.
* However, even if create_storage is true, no storage will be
* created if the relkind is one that doesn't have storage.
* *
* rel->rd_rel is initialized by RelationBuildLocalRelation, * rel->rd_rel is initialized by RelationBuildLocalRelation,
* and is mostly zeroes at return. * and is mostly zeroes at return.
@ -306,9 +312,9 @@ heap_create(const char *relname,
bool mapped_relation, bool mapped_relation,
bool allow_system_table_mods, bool allow_system_table_mods,
TransactionId *relfrozenxid, TransactionId *relfrozenxid,
MultiXactId *relminmxid) MultiXactId *relminmxid,
bool create_storage)
{ {
bool create_storage;
Relation rel; Relation rel;
/* The caller must have provided an OID for the relation. */ /* The caller must have provided an OID for the relation. */
@ -343,16 +349,16 @@ heap_create(const char *relname,
if (!RELKIND_HAS_TABLESPACE(relkind)) if (!RELKIND_HAS_TABLESPACE(relkind))
reltablespace = InvalidOid; reltablespace = InvalidOid;
/* /* Don't create storage for relkinds without physical storage. */
* Decide whether to create storage. If caller passed a valid relfilenode, if (!RELKIND_HAS_STORAGE(relkind))
* storage is already created, so don't do it here. Also don't create it
* for relkinds without physical storage.
*/
if (!RELKIND_HAS_STORAGE(relkind) || OidIsValid(relfilenode))
create_storage = false; create_storage = false;
else else
{ {
create_storage = true; /*
* If relfilenode is unspecified by the caller then create storage
* with oid same as relid.
*/
if (!OidIsValid(relfilenode))
relfilenode = relid; relfilenode = relid;
} }
@ -1121,6 +1127,9 @@ heap_create_with_catalog(const char *relname,
Oid existing_relid; Oid existing_relid;
Oid old_type_oid; Oid old_type_oid;
Oid new_type_oid; Oid new_type_oid;
/* By default set to InvalidOid unless overridden by binary-upgrade */
Oid relfilenode = InvalidOid;
TransactionId relfrozenxid; TransactionId relfrozenxid;
MultiXactId relminmxid; MultiXactId relminmxid;
@ -1183,7 +1192,7 @@ heap_create_with_catalog(const char *relname,
*/ */
if (!OidIsValid(relid)) if (!OidIsValid(relid))
{ {
/* Use binary-upgrade override for pg_class.oid/relfilenode? */ /* Use binary-upgrade override for pg_class.oid and relfilenode */
if (IsBinaryUpgrade) if (IsBinaryUpgrade)
{ {
/* /*
@ -1200,6 +1209,14 @@ heap_create_with_catalog(const char *relname,
{ {
relid = binary_upgrade_next_toast_pg_class_oid; relid = binary_upgrade_next_toast_pg_class_oid;
binary_upgrade_next_toast_pg_class_oid = InvalidOid; binary_upgrade_next_toast_pg_class_oid = InvalidOid;
if (!OidIsValid(binary_upgrade_next_toast_pg_class_relfilenode))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("toast relfilenode value not set when in binary upgrade mode")));
relfilenode = binary_upgrade_next_toast_pg_class_relfilenode;
binary_upgrade_next_toast_pg_class_relfilenode = InvalidOid;
} }
} }
else else
@ -1211,6 +1228,17 @@ heap_create_with_catalog(const char *relname,
relid = binary_upgrade_next_heap_pg_class_oid; relid = binary_upgrade_next_heap_pg_class_oid;
binary_upgrade_next_heap_pg_class_oid = InvalidOid; binary_upgrade_next_heap_pg_class_oid = InvalidOid;
if (RELKIND_HAS_STORAGE(relkind))
{
if (!OidIsValid(binary_upgrade_next_heap_pg_class_relfilenode))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("relfilenode value not set when in binary upgrade mode")));
relfilenode = binary_upgrade_next_heap_pg_class_relfilenode;
binary_upgrade_next_heap_pg_class_relfilenode = InvalidOid;
}
} }
} }
@ -1250,12 +1278,16 @@ heap_create_with_catalog(const char *relname,
* Create the relcache entry (mostly dummy at this point) and the physical * Create the relcache entry (mostly dummy at this point) and the physical
* disk file. (If we fail further down, it's the smgr's responsibility to * disk file. (If we fail further down, it's the smgr's responsibility to
* remove the disk file again.) * remove the disk file again.)
*
* NB: Note that passing create_storage = true is correct even for binary
* upgrade. The storage we create here will be replaced later, but we need
* to have something on disk in the meanwhile.
*/ */
new_rel_desc = heap_create(relname, new_rel_desc = heap_create(relname,
relnamespace, relnamespace,
reltablespace, reltablespace,
relid, relid,
InvalidOid, relfilenode,
accessmtd, accessmtd,
tupdesc, tupdesc,
relkind, relkind,
@ -1264,7 +1296,8 @@ heap_create_with_catalog(const char *relname,
mapped_relation, mapped_relation,
allow_system_table_mods, allow_system_table_mods,
&relfrozenxid, &relfrozenxid,
&relminmxid); &relminmxid,
true);
Assert(relid == RelationGetRelid(new_rel_desc)); Assert(relid == RelationGetRelid(new_rel_desc));

View File

@ -87,6 +87,7 @@
/* Potentially set by pg_upgrade_support functions */ /* Potentially set by pg_upgrade_support functions */
Oid binary_upgrade_next_index_pg_class_oid = InvalidOid; Oid binary_upgrade_next_index_pg_class_oid = InvalidOid;
Oid binary_upgrade_next_index_pg_class_relfilenode = InvalidOid;
/* /*
* Pointer-free representation of variables used when reindexing system * Pointer-free representation of variables used when reindexing system
@ -733,6 +734,7 @@ index_create(Relation heapRelation,
char relkind; char relkind;
TransactionId relfrozenxid; TransactionId relfrozenxid;
MultiXactId relminmxid; MultiXactId relminmxid;
bool create_storage = !OidIsValid(relFileNode);
/* constraint flags can only be set when a constraint is requested */ /* constraint flags can only be set when a constraint is requested */
Assert((constr_flags == 0) || Assert((constr_flags == 0) ||
@ -904,7 +906,7 @@ index_create(Relation heapRelation,
*/ */
if (!OidIsValid(indexRelationId)) if (!OidIsValid(indexRelationId))
{ {
/* Use binary-upgrade override for pg_class.oid/relfilenode? */ /* Use binary-upgrade override for pg_class.oid and relfilenode */
if (IsBinaryUpgrade) if (IsBinaryUpgrade)
{ {
if (!OidIsValid(binary_upgrade_next_index_pg_class_oid)) if (!OidIsValid(binary_upgrade_next_index_pg_class_oid))
@ -914,6 +916,22 @@ index_create(Relation heapRelation,
indexRelationId = binary_upgrade_next_index_pg_class_oid; indexRelationId = binary_upgrade_next_index_pg_class_oid;
binary_upgrade_next_index_pg_class_oid = InvalidOid; binary_upgrade_next_index_pg_class_oid = InvalidOid;
/* Overide the index relfilenode */
if ((relkind == RELKIND_INDEX) &&
(!OidIsValid(binary_upgrade_next_index_pg_class_relfilenode)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("index relfilenode value not set when in binary upgrade mode")));
relFileNode = binary_upgrade_next_index_pg_class_relfilenode;
binary_upgrade_next_index_pg_class_relfilenode = InvalidOid;
/*
* Note that we want create_storage = true for binary upgrade.
* The storage we create here will be replaced later, but we need
* to have something on disk in the meanwhile.
*/
Assert(create_storage);
} }
else else
{ {
@ -940,7 +958,8 @@ index_create(Relation heapRelation,
mapped_relation, mapped_relation,
allow_system_table_mods, allow_system_table_mods,
&relfrozenxid, &relfrozenxid,
&relminmxid); &relminmxid,
create_storage);
Assert(relfrozenxid == InvalidTransactionId); Assert(relfrozenxid == InvalidTransactionId);
Assert(relminmxid == InvalidMultiXactId); Assert(relminmxid == InvalidMultiXactId);

View File

@ -89,6 +89,7 @@ char *default_tablespace = NULL;
char *temp_tablespaces = NULL; char *temp_tablespaces = NULL;
bool allow_in_place_tablespaces = false; bool allow_in_place_tablespaces = false;
Oid binary_upgrade_next_pg_tablespace_oid = InvalidOid;
static void create_tablespace_directories(const char *location, static void create_tablespace_directories(const char *location,
const Oid tablespaceoid); const Oid tablespaceoid);
@ -340,6 +341,18 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
MemSet(nulls, false, sizeof(nulls)); MemSet(nulls, false, sizeof(nulls));
if (IsBinaryUpgrade)
{
/* Use binary-upgrade override for tablespace oid */
if (!OidIsValid(binary_upgrade_next_pg_tablespace_oid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("pg_tablespace OID value not set when in binary upgrade mode")));
tablespaceoid = binary_upgrade_next_pg_tablespace_oid;
binary_upgrade_next_pg_tablespace_oid = InvalidOid;
}
else
tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId, tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
Anum_pg_tablespace_oid); Anum_pg_tablespace_oid);
values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid); values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);

View File

@ -29,6 +29,17 @@ do { \
errmsg("function can only be called when server is in binary upgrade mode"))); \ errmsg("function can only be called when server is in binary upgrade mode"))); \
} while (0) } while (0)
Datum
binary_upgrade_set_next_pg_tablespace_oid(PG_FUNCTION_ARGS)
{
Oid tbspoid = PG_GETARG_OID(0);
CHECK_IS_BINARY_UPGRADE;
binary_upgrade_next_pg_tablespace_oid = tbspoid;
PG_RETURN_VOID();
}
Datum Datum
binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS) binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
{ {
@ -84,6 +95,17 @@ binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
Datum
binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
{
Oid nodeoid = PG_GETARG_OID(0);
CHECK_IS_BINARY_UPGRADE;
binary_upgrade_next_heap_pg_class_relfilenode = nodeoid;
PG_RETURN_VOID();
}
Datum Datum
binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS) binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
{ {
@ -95,6 +117,17 @@ binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
Datum
binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
{
Oid nodeoid = PG_GETARG_OID(0);
CHECK_IS_BINARY_UPGRADE;
binary_upgrade_next_index_pg_class_relfilenode = nodeoid;
PG_RETURN_VOID();
}
Datum Datum
binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS) binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
{ {
@ -106,6 +139,17 @@ binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
Datum
binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
{
Oid nodeoid = PG_GETARG_OID(0);
CHECK_IS_BINARY_UPGRADE;
binary_upgrade_next_toast_pg_class_relfilenode = nodeoid;
PG_RETURN_VOID();
}
Datum Datum
binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS) binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
{ {

View File

@ -4626,74 +4626,106 @@ static void
binary_upgrade_set_pg_class_oids(Archive *fout, binary_upgrade_set_pg_class_oids(Archive *fout,
PQExpBuffer upgrade_buffer, Oid pg_class_oid, PQExpBuffer upgrade_buffer, Oid pg_class_oid,
bool is_index) bool is_index)
{
appendPQExpBufferStr(upgrade_buffer,
"\n-- For binary upgrade, must preserve pg_class oids\n");
if (!is_index)
{ {
PQExpBuffer upgrade_query = createPQExpBuffer(); PQExpBuffer upgrade_query = createPQExpBuffer();
PGresult *upgrade_res; PGresult *upgrade_res;
Oid pg_class_reltoastrelid; Oid relfilenode;
char pg_class_relkind; Oid toast_oid;
Oid pg_index_indexrelid; Oid toast_relfilenode;
char relkind;
appendPQExpBuffer(upgrade_buffer, Oid toast_index_oid;
"SELECT pg_catalog.binary_upgrade_set_next_heap_pg_class_oid('%u'::pg_catalog.oid);\n", Oid toast_index_relfilenode;
pg_class_oid);
/* /*
* Preserve the OIDs of the table's toast table and index, if any. * Preserve the OID and relfilenode of the table, table's index, table's
* Indexes cannot have toast tables, so we need not make this probe in * toast table and toast table's index if any.
* the index code path.
* *
* One complexity is that the current table definition might not * One complexity is that the current table definition might not require
* require the creation of a TOAST table, but the old database might * the creation of a TOAST table, but the old database might have a TOAST
* have a TOAST table that was created earlier, before some wide * table that was created earlier, before some wide columns were dropped.
* columns were dropped. By setting the TOAST oid we force creation * By setting the TOAST oid we force creation of the TOAST heap and index
* of the TOAST heap and index by the new backend, so we can copy the * by the new backend, so we can copy the files during binary upgrade
* files during binary upgrade without worrying about this case. * without worrying about this case.
*/ */
appendPQExpBuffer(upgrade_query, appendPQExpBuffer(upgrade_query,
"SELECT c.reltoastrelid, c.relkind, i.indexrelid " "SELECT c.relkind, c.relfilenode, c.reltoastrelid, ct.relfilenode AS toast_relfilenode, i.indexrelid, cti.relfilenode AS toast_index_relfilenode "
"FROM pg_catalog.pg_class c LEFT JOIN " "FROM pg_catalog.pg_class c LEFT JOIN "
"pg_catalog.pg_index i ON (c.reltoastrelid = i.indrelid AND i.indisvalid) " "pg_catalog.pg_index i ON (c.reltoastrelid = i.indrelid AND i.indisvalid) "
"LEFT JOIN pg_catalog.pg_class ct ON (c.reltoastrelid = ct.oid) "
"LEFT JOIN pg_catalog.pg_class AS cti ON (i.indexrelid = cti.oid) "
"WHERE c.oid = '%u'::pg_catalog.oid;", "WHERE c.oid = '%u'::pg_catalog.oid;",
pg_class_oid); pg_class_oid);
upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, relkind = *PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "relkind"));
relfilenode = atooid(PQgetvalue(upgrade_res, 0,
PQfnumber(upgrade_res, "relfilenode")));
toast_oid = atooid(PQgetvalue(upgrade_res, 0,
PQfnumber(upgrade_res, "reltoastrelid"))); PQfnumber(upgrade_res, "reltoastrelid")));
pg_class_relkind = *PQgetvalue(upgrade_res, 0, toast_relfilenode = atooid(PQgetvalue(upgrade_res, 0,
PQfnumber(upgrade_res, "relkind")); PQfnumber(upgrade_res, "toast_relfilenode")));
pg_index_indexrelid = atooid(PQgetvalue(upgrade_res, 0, toast_index_oid = atooid(PQgetvalue(upgrade_res, 0,
PQfnumber(upgrade_res, "indexrelid"))); PQfnumber(upgrade_res, "indexrelid")));
toast_index_relfilenode = atooid(PQgetvalue(upgrade_res, 0,
PQfnumber(upgrade_res, "toast_index_relfilenode")));
appendPQExpBufferStr(upgrade_buffer,
"\n-- For binary upgrade, must preserve pg_class oids and relfilenodes\n");
if (!is_index)
{
appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_heap_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_class_oid);
/*
* Not every relation has storage. Also, in a pre-v12 database,
* partitioned tables have a relfilenode, which should not be preserved
* when upgrading.
*/
if (OidIsValid(relfilenode) && relkind != RELKIND_PARTITIONED_TABLE)
appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_heap_relfilenode('%u'::pg_catalog.oid);\n",
relfilenode);
/* /*
* In a pre-v12 database, partitioned tables might be marked as having * In a pre-v12 database, partitioned tables might be marked as having
* toast tables, but we should ignore them if so. * toast tables, but we should ignore them if so.
*/ */
if (OidIsValid(pg_class_reltoastrelid) && if (OidIsValid(toast_oid) &&
pg_class_relkind != RELKIND_PARTITIONED_TABLE) relkind != RELKIND_PARTITIONED_TABLE)
{ {
appendPQExpBuffer(upgrade_buffer, appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_toast_pg_class_oid('%u'::pg_catalog.oid);\n", "SELECT pg_catalog.binary_upgrade_set_next_toast_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_class_reltoastrelid); toast_oid);
appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_toast_relfilenode('%u'::pg_catalog.oid);\n",
toast_relfilenode);
/* every toast table has an index */ /* every toast table has an index */
appendPQExpBuffer(upgrade_buffer, appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n", "SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_index_indexrelid); toast_index_oid);
appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_index_relfilenode('%u'::pg_catalog.oid);\n",
toast_index_relfilenode);
} }
PQclear(upgrade_res); PQclear(upgrade_res);
destroyPQExpBuffer(upgrade_query); destroyPQExpBuffer(upgrade_query);
} }
else else
{
/* Preserve the OID and relfilenode of the index */
appendPQExpBuffer(upgrade_buffer, appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n", "SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_class_oid); pg_class_oid);
appendPQExpBuffer(upgrade_buffer,
"SELECT pg_catalog.binary_upgrade_set_next_index_relfilenode('%u'::pg_catalog.oid);\n",
relfilenode);
}
appendPQExpBufferChar(upgrade_buffer, '\n'); appendPQExpBufferChar(upgrade_buffer, '\n');
} }

View File

@ -1066,6 +1066,9 @@ dumpTablespaces(PGconn *conn)
/* needed for buildACLCommands() */ /* needed for buildACLCommands() */
fspcname = pg_strdup(fmtId(spcname)); fspcname = pg_strdup(fmtId(spcname));
appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_tablespace oid\n");
appendPQExpBuffer(buf, "SELECT pg_catalog.binary_upgrade_set_next_pg_tablespace_oid('%u'::pg_catalog.oid);\n", spcoid);
appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname); appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner)); appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));

View File

@ -193,14 +193,8 @@ create_rel_filename_map(const char *old_data, const char *new_data,
map->old_db_oid = old_db->db_oid; map->old_db_oid = old_db->db_oid;
map->new_db_oid = new_db->db_oid; map->new_db_oid = new_db->db_oid;
/* /* relfilenode is preserved across old and new cluster */
* old_relfilenode might differ from pg_class.oid (and hence map->relfilenode = old_rel->relfilenode;
* new_relfilenode) because of CLUSTER, REINDEX, or VACUUM FULL.
*/
map->old_relfilenode = old_rel->relfilenode;
/* new_relfilenode will match old and new pg_class.oid */
map->new_relfilenode = new_rel->relfilenode;
/* used only for logging and error reporting, old/new are identical */ /* used only for logging and error reporting, old/new are identical */
map->nspname = old_rel->nspname; map->nspname = old_rel->nspname;
@ -272,27 +266,6 @@ report_unmatched_relation(const RelInfo *rel, const DbInfo *db, bool is_new_db)
reloid, db->db_name, reldesc); reloid, db->db_name, reldesc);
} }
void
print_maps(FileNameMap *maps, int n_maps, const char *db_name)
{
if (log_opts.verbose)
{
int mapnum;
pg_log(PG_VERBOSE, "mappings for database \"%s\":\n", db_name);
for (mapnum = 0; mapnum < n_maps; mapnum++)
pg_log(PG_VERBOSE, "%s.%s: %u to %u\n",
maps[mapnum].nspname, maps[mapnum].relname,
maps[mapnum].old_relfilenode,
maps[mapnum].new_relfilenode);
pg_log(PG_VERBOSE, "\n\n");
}
}
/* /*
* get_db_and_rel_infos() * get_db_and_rel_infos()
* *

View File

@ -15,12 +15,13 @@
* oids are the same between old and new clusters. This is important * oids are the same between old and new clusters. This is important
* because toast oids are stored as toast pointers in user tables. * because toast oids are stored as toast pointers in user tables.
* *
* While pg_class.oid and pg_class.relfilenode are initially the same * While pg_class.oid and pg_class.relfilenode are initially the same in a
* in a cluster, they can diverge due to CLUSTER, REINDEX, or VACUUM * cluster, they can diverge due to CLUSTER, REINDEX, or VACUUM FULL. We
* FULL. In the new cluster, pg_class.oid and pg_class.relfilenode will * control assignments of pg_class.relfilenode because we want the filenames
* be the same and will match the old pg_class.oid value. Because of * to match between the old and new cluster.
* this, old/new pg_class.relfilenode values will not match if CLUSTER, *
* REINDEX, or VACUUM FULL have been performed in the old cluster. * We control assignment of pg_tablespace.oid because we want the oid to match
* between the old and new cluster.
* *
* We control all assignments of pg_type.oid because these oids are stored * We control all assignments of pg_type.oid because these oids are stored
* in user composite type values. * in user composite type values.

View File

@ -147,13 +147,7 @@ typedef struct
const char *new_tablespace_suffix; const char *new_tablespace_suffix;
Oid old_db_oid; Oid old_db_oid;
Oid new_db_oid; Oid new_db_oid;
Oid relfilenode;
/*
* old/new relfilenodes might differ for pg_largeobject(_metadata) indexes
* due to VACUUM FULL or REINDEX. Other relfilenodes are preserved.
*/
Oid old_relfilenode;
Oid new_relfilenode;
/* the rest are used only for logging and error reporting */ /* the rest are used only for logging and error reporting */
char *nspname; /* namespaces */ char *nspname; /* namespaces */
char *relname; char *relname;
@ -379,8 +373,6 @@ FileNameMap *gen_db_file_maps(DbInfo *old_db,
DbInfo *new_db, int *nmaps, const char *old_pgdata, DbInfo *new_db, int *nmaps, const char *old_pgdata,
const char *new_pgdata); const char *new_pgdata);
void get_db_and_rel_infos(ClusterInfo *cluster); void get_db_and_rel_infos(ClusterInfo *cluster);
void print_maps(FileNameMap *maps, int n,
const char *db_name);
/* option.c */ /* option.c */

View File

@ -119,8 +119,6 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
new_pgdata); new_pgdata);
if (n_maps) if (n_maps)
{ {
print_maps(mappings, n_maps, new_db->db_name);
transfer_single_new_db(mappings, n_maps, old_tablespace); transfer_single_new_db(mappings, n_maps, old_tablespace);
} }
/* We allocate something even for n_maps == 0 */ /* We allocate something even for n_maps == 0 */
@ -196,14 +194,14 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro
map->old_tablespace, map->old_tablespace,
map->old_tablespace_suffix, map->old_tablespace_suffix,
map->old_db_oid, map->old_db_oid,
map->old_relfilenode, map->relfilenode,
type_suffix, type_suffix,
extent_suffix); extent_suffix);
snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s", snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s",
map->new_tablespace, map->new_tablespace,
map->new_tablespace_suffix, map->new_tablespace_suffix,
map->new_db_oid, map->new_db_oid,
map->new_relfilenode, map->relfilenode,
type_suffix, type_suffix,
extent_suffix); extent_suffix);

View File

@ -14,14 +14,19 @@
#ifndef BINARY_UPGRADE_H #ifndef BINARY_UPGRADE_H
#define BINARY_UPGRADE_H #define BINARY_UPGRADE_H
extern PGDLLIMPORT Oid binary_upgrade_next_pg_tablespace_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid; extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_array_pg_type_oid; extern PGDLLIMPORT Oid binary_upgrade_next_array_pg_type_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_mrng_pg_type_oid; extern PGDLLIMPORT Oid binary_upgrade_next_mrng_pg_type_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_mrng_array_pg_type_oid; extern PGDLLIMPORT Oid binary_upgrade_next_mrng_array_pg_type_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_heap_pg_class_oid; extern PGDLLIMPORT Oid binary_upgrade_next_heap_pg_class_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_heap_pg_class_relfilenode;
extern PGDLLIMPORT Oid binary_upgrade_next_index_pg_class_oid; extern PGDLLIMPORT Oid binary_upgrade_next_index_pg_class_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_index_pg_class_relfilenode;
extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_class_oid; extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_class_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_class_relfilenode;
extern PGDLLIMPORT Oid binary_upgrade_next_pg_enum_oid; extern PGDLLIMPORT Oid binary_upgrade_next_pg_enum_oid;
extern PGDLLIMPORT Oid binary_upgrade_next_pg_authid_oid; extern PGDLLIMPORT Oid binary_upgrade_next_pg_authid_oid;

View File

@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202201161 #define CATALOG_VERSION_NO 202201171
#endif #endif

View File

@ -59,7 +59,8 @@ extern Relation heap_create(const char *relname,
bool mapped_relation, bool mapped_relation,
bool allow_system_table_mods, bool allow_system_table_mods,
TransactionId *relfrozenxid, TransactionId *relfrozenxid,
MultiXactId *relminmxid); MultiXactId *relminmxid,
bool create_storage);
extern Oid heap_create_with_catalog(const char *relname, extern Oid heap_create_with_catalog(const char *relname,
Oid relnamespace, Oid relnamespace,

View File

@ -11040,6 +11040,22 @@
proname => 'binary_upgrade_set_missing_value', provolatile => 'v', proname => 'binary_upgrade_set_missing_value', provolatile => 'v',
proparallel => 'u', prorettype => 'void', proargtypes => 'oid text text', proparallel => 'u', prorettype => 'void', proargtypes => 'oid text text',
prosrc => 'binary_upgrade_set_missing_value' }, prosrc => 'binary_upgrade_set_missing_value' },
{ oid => '4545', descr => 'for use by pg_upgrade',
proname => 'binary_upgrade_set_next_heap_relfilenode', provolatile => 'v',
proparallel => 'u', prorettype => 'void', proargtypes => 'oid',
prosrc => 'binary_upgrade_set_next_heap_relfilenode' },
{ oid => '4546', descr => 'for use by pg_upgrade',
proname => 'binary_upgrade_set_next_index_relfilenode', provolatile => 'v',
proparallel => 'u', prorettype => 'void', proargtypes => 'oid',
prosrc => 'binary_upgrade_set_next_index_relfilenode' },
{ oid => '4547', descr => 'for use by pg_upgrade',
proname => 'binary_upgrade_set_next_toast_relfilenode', provolatile => 'v',
proparallel => 'u', prorettype => 'void', proargtypes => 'oid',
prosrc => 'binary_upgrade_set_next_toast_relfilenode' },
{ oid => '4548', descr => 'for use by pg_upgrade',
proname => 'binary_upgrade_set_next_pg_tablespace_oid', provolatile => 'v',
proparallel => 'u', prorettype => 'void', proargtypes => 'oid',
prosrc => 'binary_upgrade_set_next_pg_tablespace_oid' },
# conversion functions # conversion functions
{ oid => '4302', { oid => '4302',

View File

@ -52,14 +52,18 @@ select * from t
------------------------------------------------------+----+------------------------------------------------------ ------------------------------------------------------+----+------------------------------------------------------
binary_upgrade_set_next_array_pg_type_oid | | binary_upgrade_set_next_array_pg_type_oid binary_upgrade_set_next_array_pg_type_oid | | binary_upgrade_set_next_array_pg_type_oid
binary_upgrade_set_next_heap_pg_class_oid | | binary_upgrade_set_next_heap_pg_class_oid binary_upgrade_set_next_heap_pg_class_oid | | binary_upgrade_set_next_heap_pg_class_oid
binary_upgrade_set_next_heap_relfilenode | 1 | binary_upgrade_set_next_heap_relfilenode
binary_upgrade_set_next_index_pg_class_oid | 1 | binary_upgrade_set_next_index_pg_class_oid binary_upgrade_set_next_index_pg_class_oid | 1 | binary_upgrade_set_next_index_pg_class_oid
binary_upgrade_set_next_index_relfilenode | | binary_upgrade_set_next_index_relfilenode
binary_upgrade_set_next_multirange_array_pg_type_oid | 1 | binary_upgrade_set_next_multirange_array_pg_type_oid binary_upgrade_set_next_multirange_array_pg_type_oid | 1 | binary_upgrade_set_next_multirange_array_pg_type_oid
binary_upgrade_set_next_multirange_pg_type_oid | 1 | binary_upgrade_set_next_multirange_pg_type_oid binary_upgrade_set_next_multirange_pg_type_oid | 1 | binary_upgrade_set_next_multirange_pg_type_oid
binary_upgrade_set_next_pg_authid_oid | | binary_upgrade_set_next_pg_authid_oid binary_upgrade_set_next_pg_authid_oid | | binary_upgrade_set_next_pg_authid_oid
binary_upgrade_set_next_pg_enum_oid | | binary_upgrade_set_next_pg_enum_oid binary_upgrade_set_next_pg_enum_oid | | binary_upgrade_set_next_pg_enum_oid
binary_upgrade_set_next_pg_tablespace_oid | | binary_upgrade_set_next_pg_tablespace_oid
binary_upgrade_set_next_pg_type_oid | | binary_upgrade_set_next_pg_type_oid binary_upgrade_set_next_pg_type_oid | | binary_upgrade_set_next_pg_type_oid
binary_upgrade_set_next_toast_pg_class_oid | 1 | binary_upgrade_set_next_toast_pg_class_oid binary_upgrade_set_next_toast_pg_class_oid | 1 | binary_upgrade_set_next_toast_pg_class_oid
(9 rows) binary_upgrade_set_next_toast_relfilenode | | binary_upgrade_set_next_toast_relfilenode
(13 rows)
-- Verify clean failure when INCLUDE'd columns result in overlength tuple -- Verify clean failure when INCLUDE'd columns result in overlength tuple
-- The error message details are platform-dependent, so show only SQLSTATE -- The error message details are platform-dependent, so show only SQLSTATE
@ -97,14 +101,18 @@ select * from t
------------------------------------------------------+----+------------------------------------------------------ ------------------------------------------------------+----+------------------------------------------------------
binary_upgrade_set_next_array_pg_type_oid | | binary_upgrade_set_next_array_pg_type_oid binary_upgrade_set_next_array_pg_type_oid | | binary_upgrade_set_next_array_pg_type_oid
binary_upgrade_set_next_heap_pg_class_oid | | binary_upgrade_set_next_heap_pg_class_oid binary_upgrade_set_next_heap_pg_class_oid | | binary_upgrade_set_next_heap_pg_class_oid
binary_upgrade_set_next_heap_relfilenode | 1 | binary_upgrade_set_next_heap_relfilenode
binary_upgrade_set_next_index_pg_class_oid | 1 | binary_upgrade_set_next_index_pg_class_oid binary_upgrade_set_next_index_pg_class_oid | 1 | binary_upgrade_set_next_index_pg_class_oid
binary_upgrade_set_next_index_relfilenode | | binary_upgrade_set_next_index_relfilenode
binary_upgrade_set_next_multirange_array_pg_type_oid | 1 | binary_upgrade_set_next_multirange_array_pg_type_oid binary_upgrade_set_next_multirange_array_pg_type_oid | 1 | binary_upgrade_set_next_multirange_array_pg_type_oid
binary_upgrade_set_next_multirange_pg_type_oid | 1 | binary_upgrade_set_next_multirange_pg_type_oid binary_upgrade_set_next_multirange_pg_type_oid | 1 | binary_upgrade_set_next_multirange_pg_type_oid
binary_upgrade_set_next_pg_authid_oid | | binary_upgrade_set_next_pg_authid_oid binary_upgrade_set_next_pg_authid_oid | | binary_upgrade_set_next_pg_authid_oid
binary_upgrade_set_next_pg_enum_oid | | binary_upgrade_set_next_pg_enum_oid binary_upgrade_set_next_pg_enum_oid | | binary_upgrade_set_next_pg_enum_oid
binary_upgrade_set_next_pg_tablespace_oid | | binary_upgrade_set_next_pg_tablespace_oid
binary_upgrade_set_next_pg_type_oid | | binary_upgrade_set_next_pg_type_oid binary_upgrade_set_next_pg_type_oid | | binary_upgrade_set_next_pg_type_oid
binary_upgrade_set_next_toast_pg_class_oid | 1 | binary_upgrade_set_next_toast_pg_class_oid binary_upgrade_set_next_toast_pg_class_oid | 1 | binary_upgrade_set_next_toast_pg_class_oid
(9 rows) binary_upgrade_set_next_toast_relfilenode | | binary_upgrade_set_next_toast_relfilenode
(13 rows)
\set VERBOSITY sqlstate \set VERBOSITY sqlstate
insert into t values(repeat('xyzzy', 12), 42, repeat('xyzzy', 4000)); insert into t values(repeat('xyzzy', 12), 42, repeat('xyzzy', 4000));