pg_upgrade: Preserve relfilenodes and tablespace OIDs.
authorRobert Haas <rhaas@postgresql.org>
Mon, 17 Jan 2022 18:32:44 +0000 (13:32 -0500)
committerRobert Haas <rhaas@postgresql.org>
Mon, 17 Jan 2022 18:40:27 +0000 (13:40 -0500)
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

16 files changed:
src/backend/bootstrap/bootparse.y
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/tablespace.c
src/backend/utils/adt/pg_upgrade_support.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.c
src/bin/pg_upgrade/info.c
src/bin/pg_upgrade/pg_upgrade.c
src/bin/pg_upgrade/pg_upgrade.h
src/bin/pg_upgrade/relfilenode.c
src/include/catalog/binary_upgrade.h
src/include/catalog/catversion.h
src/include/catalog/heap.h
src/include/catalog/pg_proc.dat
src/test/modules/spgist_name_ops/expected/spgist_name_ops.out

index f1dd95cfad81bcb4ba0e2356f4eb21fa22541f22..142433f63f3fa29345faa623a4ec45003d9428ff 100644 (file)
@@ -212,7 +212,8 @@ Boot_CreateStmt:
                                                   mapped_relation,
                                                   true,
                                                   &relfrozenxid,
-                                                  &relminmxid);
+                                                  &relminmxid,
+                                                  true);
                        elog(DEBUG4, "bootstrap relation created");
                    }
                    else
index 56215496ffe9127012a6805fd8ca860b5fc7d0db..7e99de88b343651d2757cacfe08943f0f383dcb3 100644 (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));
 
index 4506cbcf0310e813302139b7380f775349e1f7a8..e4203819a0e9e2337a7ac641ec368d0f8e00d59d 100644 (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);
index 7123b4069b4ff22cf2f6a882e5e35cc82f57e0c1..b2ccf5e06efda5c17d51e9e1d25313be92ceff89 100644 (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));
index c651f0eb814790565ef04389cc76d7e02e1f8df6..67b9675e92a4b3a9c74c1399bf01e66fbf37245c 100644 (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)
 {
index c5f231118bd0bab89251c1ec9e0092903d50a60f..7c2f1d3044721e714ebc50789d8079f17dabb1a1 100644 (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');
 }
index 94852e7cdbbf8076fd828474e2fc3d9deb6b2a58..10383c713fee56a4247eb7b8e027843c15444679 100644 (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));
 
index 60e9cc5a52c9a506b9dff686afc204dca6a0e568..f7fa0820d69ad5c84254cf6ce3f6c479938c7819 100644 (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()
  *
index 68b336e0a346389696117f8d3ce62202ff702f4a..07defacd673223ca46970a0d4be8202f5439f8d6 100644 (file)
  * 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.
index dd4a5437316a65d35b20073e0e666690e5d830d3..da6770d0f834b693ce7bed0dc63e81ad5d6eb831 100644 (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 */
 
index 302ee2b31437aba2477745d838e971e31ea34a06..6e0253cc3e61cf78ba4444139b308f060230f7db 100644 (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);
 
index cc16a26a43b123da72822e88e1bc83b245b5d986..0b6944b29cfa284fd731882814cafac0a755ba34 100644 (file)
 #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;
index 8324d957633ed296cc38dcbdedafaa96d090af8e..64b9aa36d8ba6af222ae66c6ec1fdd8957d9c4f7 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202201161
+#define CATALOG_VERSION_NO 202201171
 
 #endif
index 3b9600603f73904a3a659383f92e74b40ef43677..c4757bda2d5f08c7750ac15ef0ffa7dbb9d3e072 100644 (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,
index d6bf1f3274bb9f5b52a8717a0020057913bb8fe7..b6f689e8d1e32d07f05da99b90d7845f4e023210 100644 (file)
   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',
index ac0ddcecead78ccef253fa86efdd5bb6cb5c69de..1ee65ede24300b4515ac1c7b639b77cff9cd7e8a 100644 (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));