Some RELKIND macro refactoring
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 3 Dec 2021 12:38:26 +0000 (13:38 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 3 Dec 2021 13:08:19 +0000 (14:08 +0100)
Add more macros to group some RELKIND_* macros:

- RELKIND_HAS_PARTITIONS()
- RELKIND_HAS_TABLESPACE()
- RELKIND_HAS_TABLE_AM()

Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Alvaro Herrera <alvherre@alvh.no-ip.org>
Discussion: https://www.postgresql.org/message-id/flat/a574c8f1-9c84-93ad-a9e5-65233d6fc00f%40enterprisedb.com

14 files changed:
contrib/amcheck/verify_heapam.c
contrib/pg_surgery/heap_surgery.c
contrib/pg_visibility/pg_visibility.c
contrib/pgstattuple/pgstattuple.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/indexcmds.c
src/backend/commands/tablecmds.c
src/backend/optimizer/util/plancat.c
src/backend/storage/buffer/bufmgr.c
src/backend/utils/adt/partitionfuncs.c
src/backend/utils/cache/relcache.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/pg_class.h

index bae5340111c90c9c44f62fe27272039009c84b97..a23d0182fc06316cc561c821877ff3230bcf3d6d 100644 (file)
@@ -306,9 +306,7 @@ verify_heapam(PG_FUNCTION_ARGS)
    /*
     * Check that a relation's relkind and access method are both supported.
     */
-   if (ctx.rel->rd_rel->relkind != RELKIND_RELATION &&
-       ctx.rel->rd_rel->relkind != RELKIND_MATVIEW &&
-       ctx.rel->rd_rel->relkind != RELKIND_TOASTVALUE &&
+   if (!RELKIND_HAS_TABLE_AM(ctx.rel->rd_rel->relkind) &&
        ctx.rel->rd_rel->relkind != RELKIND_SEQUENCE)
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
index 7edfe4f326f5bc5a1cb843f5737ee1b85da11007..f06385e8d3e1904f6193c905056364752a01f16d 100644 (file)
@@ -103,9 +103,7 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt)
    /*
     * Check target relation.
     */
-   if (rel->rd_rel->relkind != RELKIND_RELATION &&
-       rel->rd_rel->relkind != RELKIND_MATVIEW &&
-       rel->rd_rel->relkind != RELKIND_TOASTVALUE)
+   if (!RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                 errmsg("cannot operate on relation \"%s\"",
index b5362edcee5ba0f445fd7c0e30177c0265726982..a206c0abd8d375c84dc497cb6dd4c92335e54fb5 100644 (file)
@@ -776,9 +776,7 @@ tuple_all_visible(HeapTuple tup, TransactionId OldestXmin, Buffer buffer)
 static void
 check_relation_relkind(Relation rel)
 {
-   if (rel->rd_rel->relkind != RELKIND_RELATION &&
-       rel->rd_rel->relkind != RELKIND_MATVIEW &&
-       rel->rd_rel->relkind != RELKIND_TOASTVALUE)
+   if (!RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                 errmsg("relation \"%s\" is of wrong relation kind",
index f408e6d84dbc38a799faa09c349fc42ced945bda..c9b8f01f9b48e9dd9c3fa749977c086c0bebe5f2 100644 (file)
@@ -252,14 +252,13 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("cannot access temporary tables of other sessions")));
 
-   switch (rel->rd_rel->relkind)
+   if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) ||
+       rel->rd_rel->relkind == RELKIND_SEQUENCE)
    {
-       case RELKIND_RELATION:
-       case RELKIND_MATVIEW:
-       case RELKIND_TOASTVALUE:
-       case RELKIND_SEQUENCE:
            return pgstat_heap(rel, fcinfo);
-       case RELKIND_INDEX:
+   }
+   else if (rel->rd_rel->relkind == RELKIND_INDEX)
+   {
            switch (rel->rd_rel->relam)
            {
                case BTREE_AM_OID:
@@ -288,9 +287,9 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("index \"%s\" (%s) is not supported",
                            RelationGetRelationName(rel), err)));
-           break;
-
-       default:
+   }
+   else
+   {
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("cannot get tuple-level statistics for relation \"%s\"",
index 8bbf23e4526c11148a79ee9d28b2be706fc0733b..eadc3ff76bab60198f08caeeb4ec189a40829ead 100644 (file)
@@ -336,35 +336,12 @@ heap_create(const char *relname,
    *relfrozenxid = InvalidTransactionId;
    *relminmxid = InvalidMultiXactId;
 
-   /* Handle reltablespace for specific relkinds. */
-   switch (relkind)
-   {
-       case RELKIND_VIEW:
-       case RELKIND_COMPOSITE_TYPE:
-       case RELKIND_FOREIGN_TABLE:
-
-           /*
-            * Force reltablespace to zero if the relation has no physical
-            * storage.  This is mainly just for cleanliness' sake.
-            *
-            * Partitioned tables and indexes don't have physical storage
-            * either, but we want to keep their tablespace settings so that
-            * their children can inherit it.
-            */
-           reltablespace = InvalidOid;
-           break;
-
-       case RELKIND_SEQUENCE:
-
-           /*
-            * Force reltablespace to zero for sequences, since we don't
-            * support moving them around into different tablespaces.
-            */
-           reltablespace = InvalidOid;
-           break;
-       default:
-           break;
-   }
+   /*
+    * Force reltablespace to zero if the relation kind does not support
+    * tablespaces.  This is mainly just for cleanliness' sake.
+    */
+   if (!RELKIND_HAS_TABLESPACE(relkind))
+       reltablespace = InvalidOid;
 
    /*
     * Decide whether to create storage. If caller passed a valid relfilenode,
@@ -409,35 +386,20 @@ heap_create(const char *relname,
    /*
     * Have the storage manager create the relation's disk file, if needed.
     *
-    * For relations the callback creates both the main and the init fork, for
-    * indexes only the main fork is created. The other forks will be created
-    * on demand.
+    * For tables, the AM callback creates both the main and the init fork.
+    * For others, only the main fork is created; the other forks will be
+    * created on demand.
     */
    if (create_storage)
    {
-       switch (rel->rd_rel->relkind)
-       {
-           case RELKIND_VIEW:
-           case RELKIND_COMPOSITE_TYPE:
-           case RELKIND_FOREIGN_TABLE:
-           case RELKIND_PARTITIONED_TABLE:
-           case RELKIND_PARTITIONED_INDEX:
-               Assert(false);
-               break;
-
-           case RELKIND_INDEX:
-           case RELKIND_SEQUENCE:
-               RelationCreateStorage(rel->rd_node, relpersistence);
-               break;
-
-           case RELKIND_RELATION:
-           case RELKIND_TOASTVALUE:
-           case RELKIND_MATVIEW:
-               table_relation_set_new_filenode(rel, &rel->rd_node,
-                                               relpersistence,
-                                               relfrozenxid, relminmxid);
-               break;
-       }
+       if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
+           table_relation_set_new_filenode(rel, &rel->rd_node,
+                                           relpersistence,
+                                           relfrozenxid, relminmxid);
+       else if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
+           RelationCreateStorage(rel->rd_node, relpersistence);
+       else
+           Assert(false);
    }
 
    /*
@@ -1015,29 +977,16 @@ AddNewRelationTuple(Relation pg_class_desc,
     */
    new_rel_reltup = new_rel_desc->rd_rel;
 
-   switch (relkind)
+   /* The relation is empty */
+   new_rel_reltup->relpages = 0;
+   new_rel_reltup->reltuples = -1;
+   new_rel_reltup->relallvisible = 0;
+
+   /* Sequences always have a known size */
+   if (relkind == RELKIND_SEQUENCE)
    {
-       case RELKIND_RELATION:
-       case RELKIND_MATVIEW:
-       case RELKIND_INDEX:
-       case RELKIND_TOASTVALUE:
-           /* The relation is real, but as yet empty */
-           new_rel_reltup->relpages = 0;
-           new_rel_reltup->reltuples = -1;
-           new_rel_reltup->relallvisible = 0;
-           break;
-       case RELKIND_SEQUENCE:
-           /* Sequences always have a known size */
-           new_rel_reltup->relpages = 1;
-           new_rel_reltup->reltuples = 1;
-           new_rel_reltup->relallvisible = 0;
-           break;
-       default:
-           /* Views, etc, have no disk storage */
-           new_rel_reltup->relpages = 0;
-           new_rel_reltup->reltuples = -1;
-           new_rel_reltup->relallvisible = 0;
-           break;
+       new_rel_reltup->relpages = 1;
+       new_rel_reltup->reltuples = 1;
    }
 
    new_rel_reltup->relfrozenxid = relfrozenxid;
@@ -1235,29 +1184,37 @@ heap_create_with_catalog(const char *relname,
    if (!OidIsValid(relid))
    {
        /* Use binary-upgrade override for pg_class.oid/relfilenode? */
-       if (IsBinaryUpgrade &&
-           (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
-            relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
-            relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
-            relkind == RELKIND_PARTITIONED_TABLE))
+       if (IsBinaryUpgrade)
        {
-           if (!OidIsValid(binary_upgrade_next_heap_pg_class_oid))
-               ereport(ERROR,
-                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                        errmsg("pg_class heap OID value not set when in binary upgrade mode")));
+           /*
+            * Indexes are not supported here; they use
+            * binary_upgrade_next_index_pg_class_oid.
+            */
+           Assert(relkind != RELKIND_INDEX);
+           Assert(relkind != RELKIND_PARTITIONED_INDEX);
 
-           relid = binary_upgrade_next_heap_pg_class_oid;
-           binary_upgrade_next_heap_pg_class_oid = InvalidOid;
-       }
-       /* There might be no TOAST table, so we have to test for it. */
-       else if (IsBinaryUpgrade &&
-                OidIsValid(binary_upgrade_next_toast_pg_class_oid) &&
-                relkind == RELKIND_TOASTVALUE)
-       {
-           relid = binary_upgrade_next_toast_pg_class_oid;
-           binary_upgrade_next_toast_pg_class_oid = InvalidOid;
+           if (relkind == RELKIND_TOASTVALUE)
+           {
+               /* There might be no TOAST table, so we have to test for it. */
+               if (OidIsValid(binary_upgrade_next_toast_pg_class_oid))
+               {
+                   relid = binary_upgrade_next_toast_pg_class_oid;
+                   binary_upgrade_next_toast_pg_class_oid = InvalidOid;
+               }
+           }
+           else
+           {
+               if (!OidIsValid(binary_upgrade_next_heap_pg_class_oid))
+                   ereport(ERROR,
+                           (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                            errmsg("pg_class heap OID value not set when in binary upgrade mode")));
+
+               relid = binary_upgrade_next_heap_pg_class_oid;
+               binary_upgrade_next_heap_pg_class_oid = InvalidOid;
+           }
        }
-       else
+
+       if (!OidIsValid(relid))
            relid = GetNewRelFileNode(reltablespace, pg_class_desc,
                                      relpersistence);
    }
@@ -1468,13 +1425,12 @@ heap_create_with_catalog(const char *relname,
 
        /*
         * Make a dependency link to force the relation to be deleted if its
-        * access method is. Do this only for relation and materialized views.
+        * access method is.
         *
         * No need to add an explicit dependency for the toast table, as the
         * main table depends on it.
         */
-       if (relkind == RELKIND_RELATION ||
-           relkind == RELKIND_MATVIEW)
+       if (RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE)
        {
            ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd);
            add_exact_object_address(&referenced, addrs);
index c255806e38cc19a69ea1731dd01d9b0862ca5061..27f0385ae0c91bba3bf663da35949a8cec6a5c33 100644 (file)
@@ -2293,7 +2293,7 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
    /*
     * Schedule physical removal of the files (if any)
     */
-   if (userIndexRelation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+   if (RELKIND_HAS_STORAGE(userIndexRelation->rd_rel->relkind))
        RelationDropStorage(userIndexRelation);
 
    /*
index c14ca27c5edf20d092bf98a9bf33d98ce14e0971..8d3104821ee0453329b85c8eab0b242edb959124 100644 (file)
@@ -2954,8 +2954,7 @@ reindex_error_callback(void *arg)
 {
    ReindexErrorInfo *errinfo = (ReindexErrorInfo *) arg;
 
-   Assert(errinfo->relkind == RELKIND_PARTITIONED_INDEX ||
-          errinfo->relkind == RELKIND_PARTITIONED_TABLE);
+   Assert(RELKIND_HAS_PARTITIONS(errinfo->relkind));
 
    if (errinfo->relkind == RELKIND_PARTITIONED_TABLE)
        errcontext("while reindexing partitioned table \"%s.%s\"",
@@ -2984,8 +2983,7 @@ ReindexPartitions(Oid relid, ReindexParams *params, bool isTopLevel)
    ErrorContextCallback errcallback;
    ReindexErrorInfo errinfo;
 
-   Assert(relkind == RELKIND_PARTITIONED_INDEX ||
-          relkind == RELKIND_PARTITIONED_TABLE);
+   Assert(RELKIND_HAS_PARTITIONS(relkind));
 
    /*
     * Check if this runs in a transaction block, with an error callback to
@@ -3118,8 +3116,7 @@ ReindexMultipleInternal(List *relids, ReindexParams *params)
         * Partitioned tables and indexes can never be processed directly, and
         * a list of their leaves should be built first.
         */
-       Assert(relkind != RELKIND_PARTITIONED_INDEX &&
-              relkind != RELKIND_PARTITIONED_TABLE);
+       Assert(!RELKIND_HAS_PARTITIONS(relkind));
 
        if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
            relpersistence != RELPERSISTENCE_TEMP)
index c35f09998c4253bbe6e0245dcd696ad60d3e94e3..c82127130696b8583f68ed5e461af12cca0cf63c 100644 (file)
@@ -916,9 +916,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
                     errmsg("specifying a table access method is not supported on a partitioned table")));
 
    }
-   else if (relkind == RELKIND_RELATION ||
-            relkind == RELKIND_TOASTVALUE ||
-            relkind == RELKIND_MATVIEW)
+   else if (RELKIND_HAS_TABLE_AM(relkind))
        accessMethod = default_table_access_method;
 
    /* look up the access method, verify it is for a table */
@@ -13995,9 +13993,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
    }
    else
    {
-       Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-              rel->rd_rel->relkind == RELKIND_MATVIEW ||
-              rel->rd_rel->relkind == RELKIND_TOASTVALUE);
+       Assert(RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind));
        table_relation_copy_data(rel, &newrnode);
    }
 
index c5194fdbbf23b5fc97e6b32a9335d77ff91e42c0..564a38a13e976112c5a3db73e0188080c591dbac 100644 (file)
@@ -965,17 +965,13 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
    BlockNumber relallvisible;
    double      density;
 
-   switch (rel->rd_rel->relkind)
+   if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
    {
-       case RELKIND_RELATION:
-       case RELKIND_MATVIEW:
-       case RELKIND_TOASTVALUE:
            table_relation_estimate_size(rel, attr_widths, pages, tuples,
                                         allvisfrac);
-           break;
-
-       case RELKIND_INDEX:
-
+   }
+   else if (rel->rd_rel->relkind == RELKIND_INDEX)
+   {
            /*
             * XXX: It'd probably be good to move this into a callback,
             * individual index types e.g. know if they have a metapage.
@@ -991,7 +987,7 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
            {
                *tuples = 0;
                *allvisfrac = 0;
-               break;
+               return;
            }
 
            /* coerce values in pg_class to more desirable types */
@@ -1055,27 +1051,18 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
                *allvisfrac = 1;
            else
                *allvisfrac = (double) relallvisible / curpages;
-           break;
-
-       case RELKIND_SEQUENCE:
-           /* Sequences always have a known size */
-           *pages = 1;
-           *tuples = 1;
-           *allvisfrac = 0;
-           break;
-       case RELKIND_FOREIGN_TABLE:
-           /* Just use whatever's in pg_class */
-           /* Note that FDW must cope if reltuples is -1! */
+   }
+   else
+   {
+           /*
+            * Just use whatever's in pg_class.  This covers foreign tables,
+            * sequences, and also relkinds without storage (shouldn't get
+            * here?); see initializations in AddNewRelationTuple().  Note
+            * that FDW must cope if reltuples is -1!
+            */
            *pages = rel->rd_rel->relpages;
            *tuples = rel->rd_rel->reltuples;
            *allvisfrac = 0;
-           break;
-       default:
-           /* else it has no disk storage; probably shouldn't get here? */
-           *pages = 0;
-           *tuples = 0;
-           *allvisfrac = 0;
-           break;
    }
 }
 
index 08ebabfe96a1788e1e337cc52943ef489214cdd8..16de918e2e1fb9f37ba55f38e149c6f5a1f924ba 100644 (file)
@@ -2934,37 +2934,26 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln)
 BlockNumber
 RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
 {
-   switch (relation->rd_rel->relkind)
+   if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
    {
-       case RELKIND_SEQUENCE:
-       case RELKIND_INDEX:
-           return smgrnblocks(RelationGetSmgr(relation), forkNum);
-
-       case RELKIND_RELATION:
-       case RELKIND_TOASTVALUE:
-       case RELKIND_MATVIEW:
-           {
-               /*
-                * Not every table AM uses BLCKSZ wide fixed size blocks.
-                * Therefore tableam returns the size in bytes - but for the
-                * purpose of this routine, we want the number of blocks.
-                * Therefore divide, rounding up.
-                */
-               uint64      szbytes;
+       /*
+        * Not every table AM uses BLCKSZ wide fixed size blocks.
+        * Therefore tableam returns the size in bytes - but for the
+        * purpose of this routine, we want the number of blocks.
+        * Therefore divide, rounding up.
+        */
+       uint64      szbytes;
 
-               szbytes = table_relation_size(relation, forkNum);
+       szbytes = table_relation_size(relation, forkNum);
 
-               return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
-           }
-       case RELKIND_VIEW:
-       case RELKIND_COMPOSITE_TYPE:
-       case RELKIND_FOREIGN_TABLE:
-       case RELKIND_PARTITIONED_INDEX:
-       case RELKIND_PARTITIONED_TABLE:
-       default:
-           Assert(false);
-           break;
+       return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
+   }
+   else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
+   {
+           return smgrnblocks(RelationGetSmgr(relation), forkNum);
    }
+   else
+       Assert(false);
 
    return 0;                   /* keep compiler quiet */
 }
index 03660d5db6c76fbba19225e1d1e64a07779c903f..61aeab75dd3a295eb0c0af8e0ee9ea32ee8e0fee 100644 (file)
@@ -45,9 +45,7 @@ check_rel_can_be_partition(Oid relid)
    relispartition = get_rel_relispartition(relid);
 
    /* Only allow relation types that can appear in partition trees. */
-   if (!relispartition &&
-       relkind != RELKIND_PARTITIONED_TABLE &&
-       relkind != RELKIND_PARTITIONED_INDEX)
+   if (!relispartition && !RELKIND_HAS_PARTITIONS(relkind))
        return false;
 
    return true;
@@ -143,8 +141,7 @@ pg_partition_tree(PG_FUNCTION_ARGS)
            nulls[1] = true;
 
        /* isleaf */
-       values[2] = BoolGetDatum(relkind != RELKIND_PARTITIONED_TABLE &&
-                                relkind != RELKIND_PARTITIONED_INDEX);
+       values[2] = BoolGetDatum(!RELKIND_HAS_PARTITIONS(relkind));
 
        /* level */
        if (relid != rootrelid)
index e1ea079e9e36348241cf94d197448ff9fbcdd79e..2b32edebe78a32f3e1190bb9adf71abe83a98b4c 100644 (file)
@@ -1203,30 +1203,14 @@ retry:
    /*
     * initialize access method information
     */
-   switch (relation->rd_rel->relkind)
-   {
-       case RELKIND_INDEX:
-       case RELKIND_PARTITIONED_INDEX:
-           Assert(relation->rd_rel->relam != InvalidOid);
-           RelationInitIndexAccessInfo(relation);
-           break;
-       case RELKIND_RELATION:
-       case RELKIND_TOASTVALUE:
-       case RELKIND_MATVIEW:
-           Assert(relation->rd_rel->relam != InvalidOid);
-           RelationInitTableAccessMethod(relation);
-           break;
-       case RELKIND_SEQUENCE:
-           Assert(relation->rd_rel->relam == InvalidOid);
-           RelationInitTableAccessMethod(relation);
-           break;
-       case RELKIND_VIEW:
-       case RELKIND_COMPOSITE_TYPE:
-       case RELKIND_FOREIGN_TABLE:
-       case RELKIND_PARTITIONED_TABLE:
-           Assert(relation->rd_rel->relam == InvalidOid);
-           break;
-   }
+   if (relation->rd_rel->relkind == RELKIND_INDEX ||
+       relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+       RelationInitIndexAccessInfo(relation);
+   else if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind) ||
+            relation->rd_rel->relkind == RELKIND_SEQUENCE)
+       RelationInitTableAccessMethod(relation);
+   else
+       Assert(relation->rd_rel->relam == InvalidOid);
 
    /* extract reloptions if any */
    RelationParseRelOptions(relation, pg_class_tuple);
@@ -1444,6 +1428,7 @@ RelationInitIndexAccessInfo(Relation relation)
    /*
     * Look up the index's access method, save the OID of its handler function
     */
+   Assert(relation->rd_rel->relam != InvalidOid);
    tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
    if (!HeapTupleIsValid(tuple))
        elog(ERROR, "cache lookup failed for access method %u",
@@ -1803,6 +1788,7 @@ RelationInitTableAccessMethod(Relation relation)
         * seem prudent to show that in the catalog. So just overwrite it
         * here.
         */
+       Assert(relation->rd_rel->relam == InvalidOid);
        relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
    }
    else if (IsCatalogRelation(relation))
@@ -3638,10 +3624,7 @@ RelationBuildLocalRelation(const char *relname,
     */
    MemoryContextSwitchTo(oldcxt);
 
-   if (relkind == RELKIND_RELATION ||
-       relkind == RELKIND_SEQUENCE ||
-       relkind == RELKIND_TOASTVALUE ||
-       relkind == RELKIND_MATVIEW)
+   if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE)
        RelationInitTableAccessMethod(rel);
 
    /*
@@ -3730,32 +3713,25 @@ RelationSetNewRelfilenode(Relation relation, char persistence)
    newrnode = relation->rd_node;
    newrnode.relNode = newrelfilenode;
 
-   switch (relation->rd_rel->relkind)
+   if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
    {
-       case RELKIND_INDEX:
-       case RELKIND_SEQUENCE:
-           {
-               /* handle these directly, at least for now */
-               SMgrRelation srel;
-
-               srel = RelationCreateStorage(newrnode, persistence);
-               smgrclose(srel);
-           }
-           break;
-
-       case RELKIND_RELATION:
-       case RELKIND_TOASTVALUE:
-       case RELKIND_MATVIEW:
-           table_relation_set_new_filenode(relation, &newrnode,
-                                           persistence,
-                                           &freezeXid, &minmulti);
-           break;
+       table_relation_set_new_filenode(relation, &newrnode,
+                                       persistence,
+                                       &freezeXid, &minmulti);
+   }
+   else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
+   {
+       /* handle these directly, at least for now */
+       SMgrRelation srel;
 
-       default:
-           /* we shouldn't be called for anything else */
-           elog(ERROR, "relation \"%s\" does not have storage",
-                RelationGetRelationName(relation));
-           break;
+       srel = RelationCreateStorage(newrnode, persistence);
+       smgrclose(srel);
+   }
+   else
+   {
+       /* we shouldn't be called for anything else */
+       elog(ERROR, "relation \"%s\" does not have storage",
+            RelationGetRelationName(relation));
    }
 
    /*
@@ -4207,10 +4183,7 @@ RelationCacheInitializePhase3(void)
 
        /* Reload tableam data if needed */
        if (relation->rd_tableam == NULL &&
-           (relation->rd_rel->relkind == RELKIND_RELATION ||
-            relation->rd_rel->relkind == RELKIND_SEQUENCE ||
-            relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
-            relation->rd_rel->relkind == RELKIND_MATVIEW))
+           (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind) || relation->rd_rel->relkind == RELKIND_SEQUENCE))
        {
            RelationInitTableAccessMethod(relation);
            Assert(relation->rd_tableam != NULL);
@@ -6127,10 +6100,7 @@ load_relcache_init_file(bool shared)
                nailed_rels++;
 
            /* Load table AM data */
-           if (rel->rd_rel->relkind == RELKIND_RELATION ||
-               rel->rd_rel->relkind == RELKIND_SEQUENCE ||
-               rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
-               rel->rd_rel->relkind == RELKIND_MATVIEW)
+           if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) || rel->rd_rel->relkind == RELKIND_SEQUENCE)
                RelationInitTableAccessMethod(rel);
 
            Assert(rel->rd_index == NULL);
index 01ffa5bf3a8a59f17c0aa3b985cc6e22404c0e37..c590003f18b7d079313163ab8128c8bee3110808 100644 (file)
@@ -16480,17 +16480,26 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
 
    if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    {
+       char       *tablespace = NULL;
        char       *tableam = NULL;
 
-       if (tbinfo->relkind == RELKIND_RELATION ||
-           tbinfo->relkind == RELKIND_MATVIEW)
+       /*
+        * _selectTablespace() relies on tablespace-enabled objects in the
+        * default tablespace to have a tablespace of "" (empty string) versus
+        * non-tablespace-enabled objects to have a tablespace of NULL.
+        * getTables() sets tbinfo->reltablespace to "" for the default
+        * tablespace (not NULL).
+        */
+       if (RELKIND_HAS_TABLESPACE(tbinfo->relkind))
+           tablespace = tbinfo->reltablespace;
+
+       if (RELKIND_HAS_TABLE_AM(tbinfo->relkind))
            tableam = tbinfo->amname;
 
        ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
                     ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
                                  .namespace = tbinfo->dobj.namespace->dobj.name,
-                                 .tablespace = (tbinfo->relkind == RELKIND_VIEW) ?
-                                 NULL : tbinfo->reltablespace,
+                                 .tablespace = tablespace,
                                  .tableam = tableam,
                                  .owner = tbinfo->rolname,
                                  .description = reltypename,
index fef9945ed8fff5c9e3041207e8388b33a7506dcc..93338d267c14b4ca9f7a86e4f2507c0899a70bd0 100644 (file)
@@ -198,6 +198,31 @@ DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeInd
     (relkind) == RELKIND_TOASTVALUE || \
     (relkind) == RELKIND_MATVIEW)
 
+#define RELKIND_HAS_PARTITIONS(relkind) \
+   ((relkind) == RELKIND_PARTITIONED_TABLE || \
+    (relkind) == RELKIND_PARTITIONED_INDEX)
+
+/*
+ * Relation kinds that support tablespaces: All relation kinds with storage
+ * support tablespaces, except that we don't support moving sequences around
+ * into different tablespaces.  Partitioned tables and indexes don't have
+ * physical storage, but they have a tablespace settings so that their
+ * children can inherit it.
+ */
+#define RELKIND_HAS_TABLESPACE(relkind) \
+   ((RELKIND_HAS_STORAGE(relkind) || RELKIND_HAS_PARTITIONS(relkind)) \
+    && (relkind) != RELKIND_SEQUENCE)
+
+/*
+ * Relation kinds with a table access method (rd_tableam).  Although sequences
+ * use the heap table AM, they are enough of a special case in most uses that
+ * they are not included here.
+ */
+#define RELKIND_HAS_TABLE_AM(relkind) \
+   ((relkind) == RELKIND_RELATION || \
+    (relkind) == RELKIND_TOASTVALUE || \
+    (relkind) == RELKIND_MATVIEW)
+
 extern int errdetail_relkind_not_supported(char relkind);
 
 #endif                         /* EXPOSE_TO_CLIENT_CODE */