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,
true,
&relfrozenxid,
&relminmxid);
&relminmxid,
true);
elog(DEBUG4, "bootstrap relation created");
}
else

View File

@ -91,7 +91,9 @@
/* Potentially set by pg_upgrade_support functions */
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_relfilenode = InvalidOid;
static void AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc,
@ -285,8 +287,12 @@ SystemAttributeByName(const char *attname)
* heap_create - Create an uncataloged heap relation
*
* Note API change: the caller must now always provide the OID
* to use for the relation. The relfilenode may (and, normally,
* should) be left unspecified.
* to use for the relation. The relfilenode may be (and in
* 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,
* and is mostly zeroes at return.
@ -306,9 +312,9 @@ heap_create(const char *relname,
bool mapped_relation,
bool allow_system_table_mods,
TransactionId *relfrozenxid,
MultiXactId *relminmxid)
MultiXactId *relminmxid,
bool create_storage)
{
bool create_storage;
Relation rel;
/* The caller must have provided an OID for the relation. */
@ -343,17 +349,17 @@ heap_create(const char *relname,
if (!RELKIND_HAS_TABLESPACE(relkind))
reltablespace = InvalidOid;
/*
* Decide whether to create storage. If caller passed a valid relfilenode,
* 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))
/* Don't create storage for relkinds without physical storage. */
if (!RELKIND_HAS_STORAGE(relkind))
create_storage = false;
else
{
create_storage = true;
relfilenode = relid;
/*
* If relfilenode is unspecified by the caller then create storage
* with oid same as relid.
*/
if (!OidIsValid(relfilenode))
relfilenode = relid;
}
/*
@ -1121,6 +1127,9 @@ heap_create_with_catalog(const char *relname,
Oid existing_relid;
Oid old_type_oid;
Oid new_type_oid;
/* By default set to InvalidOid unless overridden by binary-upgrade */
Oid relfilenode = InvalidOid;
TransactionId relfrozenxid;
MultiXactId relminmxid;
@ -1183,7 +1192,7 @@ heap_create_with_catalog(const char *relname,
*/
if (!OidIsValid(relid))
{
/* Use binary-upgrade override for pg_class.oid/relfilenode? */
/* Use binary-upgrade override for pg_class.oid and relfilenode */
if (IsBinaryUpgrade)
{
/*
@ -1200,6 +1209,14 @@ heap_create_with_catalog(const char *relname,
{
relid = binary_upgrade_next_toast_pg_class_oid;
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
@ -1211,6 +1228,17 @@ heap_create_with_catalog(const char *relname,
relid = binary_upgrade_next_heap_pg_class_oid;
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
* disk file. (If we fail further down, it's the smgr's responsibility to
* 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,
relnamespace,
reltablespace,
relid,
InvalidOid,
relfilenode,
accessmtd,
tupdesc,
relkind,
@ -1264,7 +1296,8 @@ heap_create_with_catalog(const char *relname,
mapped_relation,
allow_system_table_mods,
&relfrozenxid,
&relminmxid);
&relminmxid,
true);
Assert(relid == RelationGetRelid(new_rel_desc));

View File

@ -87,6 +87,7 @@
/* Potentially set by pg_upgrade_support functions */
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
@ -733,6 +734,7 @@ index_create(Relation heapRelation,
char relkind;
TransactionId relfrozenxid;
MultiXactId relminmxid;
bool create_storage = !OidIsValid(relFileNode);
/* constraint flags can only be set when a constraint is requested */
Assert((constr_flags == 0) ||
@ -904,7 +906,7 @@ index_create(Relation heapRelation,
*/
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 (!OidIsValid(binary_upgrade_next_index_pg_class_oid))
@ -914,6 +916,22 @@ index_create(Relation heapRelation,
indexRelationId = binary_upgrade_next_index_pg_class_oid;
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
{
@ -940,7 +958,8 @@ index_create(Relation heapRelation,
mapped_relation,
allow_system_table_mods,
&relfrozenxid,
&relminmxid);
&relminmxid,
create_storage);
Assert(relfrozenxid == InvalidTransactionId);
Assert(relminmxid == InvalidMultiXactId);

View File

@ -89,6 +89,7 @@ char *default_tablespace = NULL;
char *temp_tablespaces = NULL;
bool allow_in_place_tablespaces = false;
Oid binary_upgrade_next_pg_tablespace_oid = InvalidOid;
static void create_tablespace_directories(const char *location,
const Oid tablespaceoid);
@ -340,8 +341,20 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
MemSet(nulls, false, sizeof(nulls));
tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
Anum_pg_tablespace_oid);
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,
Anum_pg_tablespace_oid);
values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);
values[Anum_pg_tablespace_spcname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));

View File

@ -29,6 +29,17 @@ do { \
errmsg("function can only be called when server is in binary upgrade mode"))); \
} 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
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();
}
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
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();
}
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
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();
}
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
binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
{

View File

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

View File

@ -1066,6 +1066,9 @@ dumpTablespaces(PGconn *conn)
/* needed for buildACLCommands() */
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, " 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->new_db_oid = new_db->db_oid;
/*
* old_relfilenode might differ from pg_class.oid (and hence
* 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;
/* relfilenode is preserved across old and new cluster */
map->relfilenode = old_rel->relfilenode;
/* used only for logging and error reporting, old/new are identical */
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);
}
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()
*

View File

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

View File

@ -147,13 +147,7 @@ typedef struct
const char *new_tablespace_suffix;
Oid old_db_oid;
Oid new_db_oid;
/*
* 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;
Oid relfilenode;
/* the rest are used only for logging and error reporting */
char *nspname; /* namespaces */
char *relname;
@ -379,8 +373,6 @@ FileNameMap *gen_db_file_maps(DbInfo *old_db,
DbInfo *new_db, int *nmaps, const char *old_pgdata,
const char *new_pgdata);
void get_db_and_rel_infos(ClusterInfo *cluster);
void print_maps(FileNameMap *maps, int n,
const char *db_name);
/* option.c */

View File

@ -119,8 +119,6 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
new_pgdata);
if (n_maps)
{
print_maps(mappings, n_maps, new_db->db_name);
transfer_single_new_db(mappings, n_maps, old_tablespace);
}
/* 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_suffix,
map->old_db_oid,
map->old_relfilenode,
map->relfilenode,
type_suffix,
extent_suffix);
snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s",
map->new_tablespace,
map->new_tablespace_suffix,
map->new_db_oid,
map->new_relfilenode,
map->relfilenode,
type_suffix,
extent_suffix);

View File

@ -14,14 +14,19 @@
#ifndef 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_array_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_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_relfilenode;
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_authid_oid;

View File

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

View File

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

View File

@ -11040,6 +11040,22 @@
proname => 'binary_upgrade_set_missing_value', provolatile => 'v',
proparallel => 'u', prorettype => 'void', proargtypes => 'oid text text',
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
{ 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_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_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_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_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_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
-- 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_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_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_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_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_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
insert into t values(repeat('xyzzy', 12), 42, repeat('xyzzy', 4000));