On 16.08.21 16:22, Alvaro Herrera wrote:
On 2021-Aug-16, Peter Eisentraut wrote:
+ if (rel->rd_rel->relkind == RELKIND_INDEX ||
+ rel->rd_rel->relkind == RELKIND_SEQUENCE)
+ RelationCreateStorage(rel->rd_node, relpersistence);
+ else if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
+ table_relation_set_new_filenode(rel, &rel->rd_node,
+
relpersistence,
+
relfrozenxid, relminmxid);
+ else
+ Assert(false);
I think you could turn this one (and the one in RelationSetNewRelfilenode)
around:
if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
table_relation_set_new_filenode(...);
else if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
RelationCreateStorage(...);
done
+/*
+ * 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)
Partitioned tables are not listed here, but IIRC there's a patch to let
partitioned tables have a table AM so that their partitions inherit it.
I'm wondering if that patch is going to have to change this spot; and if
it does, how will that affect the callers of this macro that this patch
creates.
Interesting. It would be useful to consider both patches together then,
so that conceptual clarity is achieved. I will take a look.
After some consideration, I have removed RELKIND_HAS_INDEX_AM(), since
the way I had it and also considering that other patch effort, it didn't
make much sense.
I think a few places assume that HAS_TABLE_AM means that the
table has storage, but perhaps it would be better to spell that out
explicitly:
@@ -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) &&
RELKIND_HAS_STOAGE(ctx.rel->rd_rel->relkind)))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot check relation \"%s\"",
I think, if something has a table AM, it implies that it has storage.
In the contrib modules, the right way to phrase the check is sometimes
not entirely clear, since part of the job of these modules is sometimes
to bypass the normal APIs and do extra checks etc.
From 139464b202db0f4ac1d9df9657205914cb923911 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 16 Aug 2021 14:25:59 +0200
Subject: [PATCH v2 1/2] pg_dump: Remove redundant relkind checks
It is checked in flagInhTables() which relkinds can have parents.
After that, those entries will have numParents==0, so we don't need to
check the relkind again.
---
src/bin/pg_dump/common.c | 8 +-------
src/bin/pg_dump/pg_dump.c | 7 +------
2 files changed, 2 insertions(+), 13 deletions(-)
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 1f24e79665..7b85718075 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -501,13 +501,7 @@ flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int
numTables)
int numParents;
TableInfo **parents;
- /* Some kinds never have parents */
- if (tbinfo->relkind == RELKIND_SEQUENCE ||
- tbinfo->relkind == RELKIND_VIEW ||
- tbinfo->relkind == RELKIND_MATVIEW)
- continue;
-
- /* Don't bother computing anything for non-target tables,
either */
+ /* Don't bother computing anything for non-target tables */
if (!tbinfo->dobj.dump)
continue;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 6adbd20778..61ba557466 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2725,12 +2725,7 @@ guessConstraintInheritance(TableInfo *tblinfo, int
numTables)
TableInfo **parents;
TableInfo *parent;
- /* Sequences and views never have parents */
- if (tbinfo->relkind == RELKIND_SEQUENCE ||
- tbinfo->relkind == RELKIND_VIEW)
- continue;
-
- /* Don't bother computing anything for non-target tables,
either */
+ /* Don't bother computing anything for non-target tables */
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
continue;
--
2.33.0
From 9fcf1c54e5d1c29318c0e94b6eba80b6ffce5824 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 30 Aug 2021 10:09:50 +0200
Subject: [PATCH v2 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 173f99d787..cd79721392 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))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot check relation \"%s\"",
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 83746d3fd9..c10124de3d 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);
}
/*
@@ -1011,29 +971,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;
@@ -1231,29 +1178,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);
}
@@ -1464,13 +1419,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 26bfa74ce7..fda930fcb0 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2283,7 +2283,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 dbee6ae199..cfb06ec832 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 */
@@ -13946,9 +13944,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 bc1753ae91..4c5650ff85 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2925,37 +2925,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 13d9994af3..f92ad6dea2 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1167,30 +1167,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);
@@ -1393,6 +1377,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",
@@ -1752,6 +1737,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))
@@ -3545,10 +3531,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);
/*
@@ -3637,32 +3620,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));
}
/*
@@ -4104,10 +4080,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);
@@ -6010,10 +5983,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 61ba557466..143166564c 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -16609,17 +16609,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.0