From 0cf76b6d91c41a86f2e3cb3a3c4cd1854b819bb5 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 30 Aug 2021 10:09:50 +0200 Subject: [PATCH v3 2/2] Some RELKIND macro refactoring Add more macros to group some RELKIND_* macros: - RELKIND_HAS_PARTITIONS() - RELKIND_HAS_TABLESPACE() - RELKIND_HAS_TABLE_AM() Discussion: https://www.postgresql.org/message-id/flat/a574c8f1-9c84-93ad-a9e5-65233d6fc00f%40enterprisedb.com --- contrib/amcheck/verify_heapam.c | 4 +- contrib/pg_surgery/heap_surgery.c | 4 +- contrib/pg_visibility/pg_visibility.c | 4 +- contrib/pgstattuple/pgstattuple.c | 17 ++- src/backend/catalog/heap.c | 154 +++++++++---------------- src/backend/catalog/index.c | 2 +- src/backend/commands/indexcmds.c | 9 +- src/backend/commands/tablecmds.c | 8 +- src/backend/optimizer/util/plancat.c | 41 +++---- src/backend/storage/buffer/bufmgr.c | 43 +++---- src/backend/utils/adt/partitionfuncs.c | 7 +- src/backend/utils/cache/relcache.c | 90 +++++---------- src/bin/pg_dump/pg_dump.c | 17 ++- src/include/catalog/pg_class.h | 25 ++++ 14 files changed, 171 insertions(+), 254 deletions(-) diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c index e84ecd1c98..59fa794450 100644 --- a/contrib/amcheck/verify_heapam.c +++ b/contrib/amcheck/verify_heapam.c @@ -303,9 +303,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), diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c index 7edfe4f326..f06385e8d3 100644 --- a/contrib/pg_surgery/heap_surgery.c +++ b/contrib/pg_surgery/heap_surgery.c @@ -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\"", diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index b5362edcee..a206c0abd8 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -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", diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index f408e6d84d..c9b8f01f9b 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -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\"", diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 81cc39fb70..a13861e925 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -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,18 @@ 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 + RelationCreateStorage(rel->rd_node, relpersistence); } /* @@ -1014,29 +974,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; @@ -1234,29 +1181,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 (!relid) relid = GetNewRelFileNode(reltablespace, pg_class_desc, relpersistence); } @@ -1467,13 +1422,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); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index c255806e38..27f0385ae0 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -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); /* diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index c14ca27c5e..8d3104821e 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -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) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 857cc5ce6e..744ed51a9a 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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 */ @@ -13981,9 +13979,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); } diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5194fdbbf..564a38a13e 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -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; } } diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 08ebabfe96..16de918e2e 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -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 */ } diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c index 03660d5db6..61aeab75dd 100644 --- a/src/backend/utils/adt/partitionfuncs.c +++ b/src/backend/utils/adt/partitionfuncs.c @@ -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) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 9fa9e671a1..e6a3e16dcf 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1203,30 +1203,14 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) /* * 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); @@ -6120,10 +6093,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); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index f3c6c28480..a5ee03bb75 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -16439,17 +16439,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, diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index fef9945ed8..93338d267c 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -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 */ -- 2.33.1