v2-0002-Refactoring-relkind-handling.patch

application/octet-stream

Filename: v2-0002-Refactoring-relkind-handling.patch
Type: application/octet-stream
Part: 0
Message: Re: Towards easier AMs: Cleaning up inappropriate use of name "relkind"

Patch

Format: format-patch
Series: patch v2-0002
Subject: Refactoring relkind handling
File+
contrib/oid2name/oid2name.c 9 9
contrib/pageinspect/rawpage.c 41 25
contrib/pgrowlocks/pgrowlocks.c 27 11
contrib/pgstattuple/pgstatapprox.c 21 7
contrib/pgstattuple/pgstatindex.c 21 9
contrib/pgstattuple/pgstattuple.c 2 1
contrib/pg_visibility/pg_visibility.c 21 7
contrib/postgres_fdw/postgres_fdw.c 5 5
contrib/sepgsql/dml.c 46 7
contrib/sepgsql/label.c 39 12
contrib/sepgsql/relation.c 277 110
contrib/vacuumlo/vacuumlo.c 1 1
src/backend/access/common/reloptions.c 14 3
src/backend/access/heap/heapam.c 61 25
src/backend/access/heap/heapam_handler.c 21 6
src/backend/access/heap/heaptoast.c 36 4
src/backend/access/index/indexam.c 22 6
src/backend/access/table/tableam.c 35 21
src/backend/access/table/table.c 78 33
src/backend/catalog/aclchk.c 277 134
src/backend/catalog/dependency.c 30 16
src/backend/catalog/heap.c 236 95
src/backend/catalog/index.c 93 17
src/backend/catalog/objectaddress.c 129 36
src/backend/catalog/partition.c 19 2
src/backend/catalog/pg_depend.c 41 10
src/backend/catalog/pg_publication.c 41 12
src/backend/catalog/pg_type.c 19 4
src/backend/catalog/toasting.c 38 8
src/backend/commands/analyze.c 141 86
src/backend/commands/cluster.c 116 38
src/backend/commands/comment.c 21 10
src/backend/commands/copy.c 143 68
src/backend/commands/extension.c 2 2
src/backend/commands/indexcmds.c 144 46
src/backend/commands/lockcmds.c 82 18
src/backend/commands/policy.c 62 16
src/backend/commands/publicationcmds.c 42 26
src/backend/commands/seclabel.c 21 10
src/backend/commands/sequence.c 21 8
src/backend/commands/statscmds.c 21 8
src/backend/commands/tablecmds.c 1755 816
src/backend/commands/trigger.c 295 154
src/backend/commands/typecmds.c 19 4
src/backend/commands/vacuum.c 80 27
src/backend/executor/execMain.c 81 38
src/backend/executor/execReplication.c 30 15
src/backend/executor/nodeModifyTable.c 101 67
src/backend/optimizer/path/allpaths.c 122 48
src/backend/optimizer/plan/planner.c 102 44
src/backend/optimizer/util/inherit.c 161 89
src/backend/optimizer/util/plancat.c 60 14
src/backend/parser/parse_utilcmd.c 136 51
src/backend/partitioning/partbounds.c 38 12
src/backend/postmaster/autovacuum.c 77 15
src/backend/replication/basebackup.c 3 3
src/backend/replication/logical/reorderbuffer.c 17 2
src/backend/replication/logical/tablesync.c 31 17
src/backend/replication/logical/worker.c 115 50
src/backend/replication/slot.c 26 26
src/backend/rewrite/rewriteDefine.c 113 72
src/backend/rewrite/rewriteHandler.c 293 170
src/backend/rewrite/rowsecurity.c 17 3
src/backend/storage/buffer/bufmgr.c 8 3
src/backend/storage/lmgr/proc.c 14 13
src/backend/storage/lmgr/spin.c 1 1
src/backend/tcop/utility.c 55 27
src/backend/utils/adt/amutils.c 17 4
src/backend/utils/adt/dbsize.c 7 7
src/backend/utils/adt/partitionfuncs.c 38 6
src/backend/utils/adt/tid.c 34 4
src/backend/utils/adt/xml.c 6 6
src/backend/utils/cache/partcache.c 17 2
src/backend/utils/cache/relcache.c 241 107
src/bin/initdb/initdb.c 10 10
src/bin/pg_dump/common.c 34 8
src/bin/pg_dump/pg_backup_tar.c 1 1
src/bin/pg_dump/pg_dump.c 149 45
src/bin/pg_dump/pg_dump_sort.c 124 45
src/bin/pg_upgrade/info.c 2 2
src/bin/pg_upgrade/pg_upgrade.c 6 6
src/bin/pg_upgrade/version.c 3 3
src/bin/psql/command.c 14 5
src/bin/psql/describe.c 1205 1063
src/bin/psql/tab-complete.c 33 33
src/bin/scripts/reindexdb.c 4 4
src/bin/scripts/vacuumdb.c 2 2
src/include/catalog/pg_class.h 28 10
src/include/nodes/execnodes.h 2 2
src/include/storage/proc.h 1 1
src/include/utils/builtins.h 5 5
src/pl/plpgsql/src/pl_comp.c 17 8
src/test/regress/regress.c 11 11
src/tools/findoidjoins/findoidjoins.c 3 3
From 41a970951670dd413c0e066512ae79c3c16533a6 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 1 Jul 2020 08:12:27 -0700
Subject: [PATCH v2 2/2] Refactoring relkind handling

Cleaning up the #define RELKIND_XXX stuff using a new RelKind enum
and special macros while keeping the relkind fields as type 'char'.
---
 contrib/oid2name/oid2name.c                   |   18 +-
 contrib/pageinspect/rawpage.c                 |   66 +-
 contrib/pg_visibility/pg_visibility.c         |   28 +-
 contrib/pgrowlocks/pgrowlocks.c               |   38 +-
 contrib/pgstattuple/pgstatapprox.c            |   28 +-
 contrib/pgstattuple/pgstatindex.c             |   30 +-
 contrib/pgstattuple/pgstattuple.c             |    3 +-
 contrib/postgres_fdw/postgres_fdw.c           |   10 +-
 contrib/sepgsql/dml.c                         |   53 +-
 contrib/sepgsql/label.c                       |   51 +-
 contrib/sepgsql/relation.c                    |  387 ++-
 contrib/vacuumlo/vacuumlo.c                   |    2 +-
 src/backend/access/common/reloptions.c        |   17 +-
 src/backend/access/heap/heapam.c              |   86 +-
 src/backend/access/heap/heapam_handler.c      |   27 +-
 src/backend/access/heap/heaptoast.c           |   40 +-
 src/backend/access/index/indexam.c            |   28 +-
 src/backend/access/table/table.c              |  111 +-
 src/backend/access/table/tableam.c            |   56 +-
 src/backend/catalog/aclchk.c                  |  411 ++-
 src/backend/catalog/dependency.c              |   46 +-
 src/backend/catalog/heap.c                    |  331 ++-
 src/backend/catalog/index.c                   |  110 +-
 src/backend/catalog/objectaddress.c           |  165 +-
 src/backend/catalog/partition.c               |   21 +-
 src/backend/catalog/pg_depend.c               |   51 +-
 src/backend/catalog/pg_publication.c          |   53 +-
 src/backend/catalog/pg_type.c                 |   23 +-
 src/backend/catalog/toasting.c                |   46 +-
 src/backend/commands/analyze.c                |  227 +-
 src/backend/commands/cluster.c                |  154 +-
 src/backend/commands/comment.c                |   31 +-
 src/backend/commands/copy.c                   |  211 +-
 src/backend/commands/extension.c              |    4 +-
 src/backend/commands/indexcmds.c              |  190 +-
 src/backend/commands/lockcmds.c               |  100 +-
 src/backend/commands/policy.c                 |   78 +-
 src/backend/commands/publicationcmds.c        |   68 +-
 src/backend/commands/seclabel.c               |   31 +-
 src/backend/commands/sequence.c               |   29 +-
 src/backend/commands/statscmds.c              |   29 +-
 src/backend/commands/tablecmds.c              | 2571 +++++++++++------
 src/backend/commands/trigger.c                |  449 ++-
 src/backend/commands/typecmds.c               |   23 +-
 src/backend/commands/vacuum.c                 |  107 +-
 src/backend/executor/execMain.c               |  119 +-
 src/backend/executor/execReplication.c        |   45 +-
 src/backend/executor/nodeModifyTable.c        |  168 +-
 src/backend/optimizer/path/allpaths.c         |  170 +-
 src/backend/optimizer/plan/planner.c          |  146 +-
 src/backend/optimizer/util/inherit.c          |  250 +-
 src/backend/optimizer/util/plancat.c          |   74 +-
 src/backend/parser/parse_utilcmd.c            |  187 +-
 src/backend/partitioning/partbounds.c         |   50 +-
 src/backend/postmaster/autovacuum.c           |   92 +-
 src/backend/replication/basebackup.c          |    6 +-
 .../replication/logical/reorderbuffer.c       |   19 +-
 src/backend/replication/logical/tablesync.c   |   48 +-
 src/backend/replication/logical/worker.c      |  165 +-
 src/backend/replication/slot.c                |   52 +-
 src/backend/rewrite/rewriteDefine.c           |  185 +-
 src/backend/rewrite/rewriteHandler.c          |  463 +--
 src/backend/rewrite/rowsecurity.c             |   20 +-
 src/backend/storage/buffer/bufmgr.c           |   11 +-
 src/backend/storage/lmgr/proc.c               |   27 +-
 src/backend/storage/lmgr/spin.c               |    2 +-
 src/backend/tcop/utility.c                    |   82 +-
 src/backend/utils/adt/amutils.c               |   21 +-
 src/backend/utils/adt/dbsize.c                |   14 +-
 src/backend/utils/adt/partitionfuncs.c        |   44 +-
 src/backend/utils/adt/tid.c                   |   38 +-
 src/backend/utils/adt/xml.c                   |   12 +-
 src/backend/utils/cache/partcache.c           |   19 +-
 src/backend/utils/cache/relcache.c            |  348 ++-
 src/bin/initdb/initdb.c                       |   20 +-
 src/bin/pg_dump/common.c                      |   42 +-
 src/bin/pg_dump/pg_backup_tar.c               |    2 +-
 src/bin/pg_dump/pg_dump.c                     |  194 +-
 src/bin/pg_dump/pg_dump_sort.c                |  169 +-
 src/bin/pg_upgrade/info.c                     |    4 +-
 src/bin/pg_upgrade/pg_upgrade.c               |   12 +-
 src/bin/pg_upgrade/version.c                  |    6 +-
 src/bin/psql/command.c                        |   19 +-
 src/bin/psql/describe.c                       | 2268 ++++++++-------
 src/bin/psql/tab-complete.c                   |   66 +-
 src/bin/scripts/reindexdb.c                   |    8 +-
 src/bin/scripts/vacuumdb.c                    |    4 +-
 src/include/catalog/pg_class.h                |   38 +-
 src/include/nodes/execnodes.h                 |    4 +-
 src/include/storage/proc.h                    |    2 +-
 src/include/utils/builtins.h                  |   10 +-
 src/pl/plpgsql/src/pl_comp.c                  |   25 +-
 src/test/regress/regress.c                    |   22 +-
 src/tools/findoidjoins/findoidjoins.c         |    6 +-
 94 files changed, 8280 insertions(+), 4156 deletions(-)

diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c
index c7d0f9025a..cff14f7c47 100644
--- a/contrib/oid2name/oid2name.c
+++ b/contrib/oid2name/oid2name.c
@@ -481,8 +481,8 @@ sql_exec_dumpalltables(PGconn *conn, struct options *opts)
 			 "	LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
 			 "	LEFT JOIN pg_catalog.pg_database d ON d.datname = pg_catalog.current_database(),"
 			 "	pg_catalog.pg_tablespace t "
-			 "WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ","
-			 CppAsString2(RELKIND_MATVIEW) "%s%s) AND "
+			 "WHERE relkind IN (" RelKindAsString(RELKIND_RELATION) ","
+			 RelKindAsString(RELKIND_MATVIEW) "%s%s) AND "
 			 "	%s"
 			 "		t.oid = CASE"
 			 "			WHEN reltablespace <> 0 THEN reltablespace"
@@ -490,8 +490,8 @@ sql_exec_dumpalltables(PGconn *conn, struct options *opts)
 			 "		END "
 			 "ORDER BY relname",
 			 opts->extended ? addfields : "",
-			 opts->indexes ? "," CppAsString2(RELKIND_INDEX) "," CppAsString2(RELKIND_SEQUENCE) : "",
-			 opts->systables ? "," CppAsString2(RELKIND_TOASTVALUE) : "",
+			 opts->indexes ? "," RelKindAsString(RELKIND_INDEX) "," RelKindAsString(RELKIND_SEQUENCE) : "",
+			 opts->systables ? "," RelKindAsString(RELKIND_TOASTVALUE) : "",
 			 opts->systables ? "" : "n.nspname NOT IN ('pg_catalog', 'information_schema') AND n.nspname !~ '^pg_toast' AND");
 
 	sql_exec(conn, todo, opts->quiet);
@@ -551,11 +551,11 @@ sql_exec_searchtables(PGconn *conn, struct options *opts)
 					"	LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
 					"	LEFT JOIN pg_catalog.pg_database d ON d.datname = pg_catalog.current_database(),\n"
 					"	pg_catalog.pg_tablespace t\n"
-					"WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ","
-					CppAsString2(RELKIND_MATVIEW) ","
-					CppAsString2(RELKIND_INDEX) ","
-					CppAsString2(RELKIND_SEQUENCE) ","
-					CppAsString2(RELKIND_TOASTVALUE) ") AND\n"
+					"WHERE relkind IN (" RelKindAsString(RELKIND_RELATION) ","
+					RelKindAsString(RELKIND_MATVIEW) ","
+					RelKindAsString(RELKIND_INDEX) ","
+					RelKindAsString(RELKIND_SEQUENCE) ","
+					RelKindAsString(RELKIND_TOASTVALUE) ") AND\n"
 					"		t.oid = CASE\n"
 					"			WHEN reltablespace <> 0 THEN reltablespace\n"
 					"			ELSE dattablespace\n"
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index c0181506a5..b7082f5cdb 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -108,31 +108,47 @@ get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
 	rel = relation_openrv(relrv, AccessShareLock);
 
 	/* Check that this relation has storage */
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot get raw page from view \"%s\"",
-						RelationGetRelationName(rel))));
-	if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot get raw page from composite type \"%s\"",
-						RelationGetRelationName(rel))));
-	if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot get raw page from foreign table \"%s\"",
-						RelationGetRelationName(rel))));
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot get raw page from partitioned table \"%s\"",
-						RelationGetRelationName(rel))));
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot get raw page from partitioned index \"%s\"",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_VIEW:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot get raw page from view \"%s\"",
+							RelationGetRelationName(rel))));
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot get raw page from composite type \"%s\"",
+							RelationGetRelationName(rel))));
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot get raw page from foreign table \"%s\"",
+							RelationGetRelationName(rel))));
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot get raw page from partitioned table \"%s\"",
+							RelationGetRelationName(rel))));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot get raw page from partitioned index \"%s\"",
+							RelationGetRelationName(rel))));
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * Reject attempts to read non-local temporary relations; we would be
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 68d580ed1e..30bcf49379 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -778,11 +778,25 @@ 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)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, materialized view, or TOAST table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table, materialized view, or TOAST table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 }
diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c
index 714398831b..a5a123d421 100644
--- a/contrib/pgrowlocks/pgrowlocks.c
+++ b/contrib/pgrowlocks/pgrowlocks.c
@@ -111,17 +111,33 @@ pgrowlocks(PG_FUNCTION_ARGS)
 		ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 						errmsg("only heap AM is supported")));
 
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is a partitioned table",
-						RelationGetRelationName(rel)),
-				 errdetail("Partitioned tables do not contain rows.")));
-	else if (rel->rd_rel->relkind != RELKIND_RELATION)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is a partitioned table",
+							RelationGetRelationName(rel)),
+					 errdetail("Partitioned tables do not contain rows.")));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 
 	/*
 	 * check permissions: must have SELECT on table or be in
diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c
index dbc0fa11f6..c14edf2aad 100644
--- a/contrib/pgstattuple/pgstatapprox.c
+++ b/contrib/pgstattuple/pgstatapprox.c
@@ -281,13 +281,27 @@ pgstattuple_approx_internal(Oid relid, FunctionCallInfo fcinfo)
 	 * We support only relation kinds with a visibility map and a free space
 	 * map.
 	 */
-	if (!(rel->rd_rel->relkind == RELKIND_RELATION ||
-		  rel->rd_rel->relkind == RELKIND_MATVIEW ||
-		  rel->rd_rel->relkind == RELKIND_TOASTVALUE))
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("\"%s\" is not a table, materialized view, or TOAST table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("\"%s\" is not a table, materialized view, or TOAST table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 
 	if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
 		ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index b1ce0d77d7..b6c1a16d15 100644
--- a/contrib/pgstattuple/pgstatindex.c
+++ b/contrib/pgstattuple/pgstatindex.c
@@ -758,13 +758,25 @@ GetHashPageStats(Page page, HashIndexStat *stats)
 static void
 check_relation_relkind(Relation rel)
 {
-	if (rel->rd_rel->relkind != RELKIND_RELATION &&
-		rel->rd_rel->relkind != RELKIND_INDEX &&
-		rel->rd_rel->relkind != RELKIND_MATVIEW &&
-		rel->rd_rel->relkind != RELKIND_SEQUENCE &&
-		rel->rd_rel->relkind != RELKIND_TOASTVALUE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, index, materialized view, sequence, or TOAST table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table, index, materialized view, sequence, or TOAST table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 }
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 69179d4104..897805d575 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -252,7 +252,7 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	switch (rel->rd_rel->relkind)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
@@ -300,6 +300,7 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
 		case RELKIND_PARTITIONED_INDEX:
 			err = "partitioned index";
 			break;
+		case RELKIND_NULL:
 		default:
 			err = "unknown";
 			break;
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 9fc53cad68..77e28757ef 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -4842,11 +4842,11 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
 
 		appendStringInfoString(&buf,
 							   "WHERE c.relkind IN ("
-							   CppAsString2(RELKIND_RELATION) ","
-							   CppAsString2(RELKIND_VIEW) ","
-							   CppAsString2(RELKIND_FOREIGN_TABLE) ","
-							   CppAsString2(RELKIND_MATVIEW) ","
-							   CppAsString2(RELKIND_PARTITIONED_TABLE) ") "
+							   RelKindAsString(RELKIND_RELATION) ","
+							   RelKindAsString(RELKIND_VIEW) ","
+							   RelKindAsString(RELKIND_FOREIGN_TABLE) ","
+							   RelKindAsString(RELKIND_MATVIEW) ","
+							   RelKindAsString(RELKIND_PARTITIONED_TABLE) ") "
 							   "  AND n.nspname = ");
 		deparseStringLiteral(&buf, stmt->remote_schema);
 
diff --git a/contrib/sepgsql/dml.c b/contrib/sepgsql/dml.c
index 53f6f41c5c..a1d5986619 100644
--- a/contrib/sepgsql/dml.c
+++ b/contrib/sepgsql/dml.c
@@ -167,10 +167,27 @@ check_relation_privileges(Oid relOid,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("SELinux: hardwired security policy violation")));
 
-		if (relkind == RELKIND_TOASTVALUE)
-			ereport(ERROR,
-					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-					 errmsg("SELinux: hardwired security policy violation")));
+		switch ((RelKind) relkind)
+		{
+			case RELKIND_TOASTVALUE:
+				ereport(ERROR,
+						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+						 errmsg("SELinux: hardwired security policy violation")));
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
+
 	}
 
 	/*
@@ -180,7 +197,7 @@ check_relation_privileges(Oid relOid,
 	object.objectId = relOid;
 	object.objectSubId = 0;
 	audit_name = getObjectIdentity(&object);
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -210,6 +227,13 @@ check_relation_privileges(Oid relOid,
 											 abort_on_violation);
 			break;
 
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			/* nothing to be checked */
 			break;
@@ -219,8 +243,23 @@ check_relation_privileges(Oid relOid,
 	/*
 	 * Only columns owned by relations shall be checked
 	 */
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		return true;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return true;
+	}
 
 	/*
 	 * Check permissions on the columns
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index 147ab67f32..697f556f58 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -763,15 +763,28 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
 			case RelationRelationId:
 				relForm = (Form_pg_class) GETSTRUCT(tuple);
 
-				if (relForm->relkind == RELKIND_RELATION ||
-					relForm->relkind == RELKIND_PARTITIONED_TABLE)
-					objtype = SELABEL_DB_TABLE;
-				else if (relForm->relkind == RELKIND_SEQUENCE)
-					objtype = SELABEL_DB_SEQUENCE;
-				else if (relForm->relkind == RELKIND_VIEW)
-					objtype = SELABEL_DB_VIEW;
-				else
-					continue;	/* no need to assign security label */
+				switch ((RelKind) relForm->relkind)
+				{
+					case RELKIND_RELATION:
+					case RELKIND_PARTITIONED_TABLE:
+						objtype = SELABEL_DB_TABLE;
+						break;
+					case RELKIND_SEQUENCE:
+						objtype = SELABEL_DB_SEQUENCE;
+						break;
+					case RELKIND_VIEW:
+						objtype = SELABEL_DB_VIEW;
+						break;
+					case RELKIND_PARTITIONED_INDEX:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_FOREIGN_TABLE:
+					case RELKIND_INDEX:
+					case RELKIND_MATVIEW:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_NULL:
+					default:
+						continue;	/* no need to assign security label */
+				}
 
 				namespace_name = get_namespace_name(relForm->relnamespace);
 				objname = quote_object_name(database_name,
@@ -788,9 +801,23 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
 			case AttributeRelationId:
 				attForm = (Form_pg_attribute) GETSTRUCT(tuple);
 
-				if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION &&
-					get_rel_relkind(attForm->attrelid) != RELKIND_PARTITIONED_TABLE)
-					continue;	/* no need to assign security label */
+				switch ((RelKind) get_rel_relkind(attForm->attrelid))
+				{
+					case RELKIND_RELATION:
+					case RELKIND_PARTITIONED_TABLE:
+						break;
+					case RELKIND_PARTITIONED_INDEX:
+					case RELKIND_SEQUENCE:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_FOREIGN_TABLE:
+					case RELKIND_INDEX:
+					case RELKIND_MATVIEW:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_VIEW:
+					case RELKIND_NULL:
+					default:
+						continue;	/* no need to assign security label */
+				}
 
 				objtype = SELABEL_DB_COLUMN;
 
diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c
index 380bc6094d..27262f47c1 100644
--- a/contrib/sepgsql/relation.c
+++ b/contrib/sepgsql/relation.c
@@ -59,8 +59,23 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
 	 * Only attributes within regular relations or partition relations have
 	 * individual security labels.
 	 */
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return;
+	}
 
 	/*
 	 * Compute a default security label of the new column underlying the
@@ -137,8 +152,23 @@ sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
 	char	   *audit_name;
 	char		relkind = get_rel_relkind(relOid);
 
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return;
+	}
 
 	/*
 	 * check db_column:{drop} permission
@@ -170,10 +200,26 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
 	char	   *audit_name;
 	char		relkind = get_rel_relkind(relOid);
 
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot set security label on non-regular columns")));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot set security label on non-regular columns")));
+			break;
+	}
 
 	object.classId = RelationRelationId;
 	object.objectId = relOid;
@@ -213,8 +259,25 @@ sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
 	char	   *audit_name;
 	char		relkind = get_rel_relkind(relOid);
 
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return;
+	}
 
 	/*
 	 * check db_column:{setattr} permission
@@ -275,9 +338,26 @@ sepgsql_relation_post_create(Oid relOid)
 	classForm = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* ignore indexes on toast tables */
-	if (classForm->relkind == RELKIND_INDEX &&
-		classForm->relnamespace == PG_TOAST_NAMESPACE)
-		goto out;
+	switch ((RelKind) classForm->relkind)
+	{
+		case RELKIND_INDEX:
+			if (classForm->relnamespace == PG_TOAST_NAMESPACE)
+				goto out;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
+
 
 	/*
 	 * check db_schema:{add_name} permission of the namespace
@@ -291,7 +371,7 @@ sepgsql_relation_post_create(Oid relOid)
 							getObjectIdentity(&object),
 							true);
 
-	switch (classForm->relkind)
+	switch ((RelKind) classForm->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -307,6 +387,12 @@ sepgsql_relation_post_create(Oid relOid)
 			/* deal with indexes specially; no need for tclass */
 			sepgsql_index_modify(relOid);
 			goto out;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			/* ignore other relkinds */
 			goto out;
@@ -348,59 +434,75 @@ sepgsql_relation_post_create(Oid relOid)
 	/*
 	 * We also assign a default security label on columns of a new table.
 	 */
-	if (classForm->relkind == RELKIND_RELATION ||
-		classForm->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) classForm->relkind)
 	{
-		Relation	arel;
-		ScanKeyData akey;
-		SysScanDesc ascan;
-		HeapTuple	atup;
-		Form_pg_attribute attForm;
-
-		arel = table_open(AttributeRelationId, AccessShareLock);
-
-		ScanKeyInit(&akey,
-					Anum_pg_attribute_attrelid,
-					BTEqualStrategyNumber, F_OIDEQ,
-					ObjectIdGetDatum(relOid));
-
-		ascan = systable_beginscan(arel, AttributeRelidNumIndexId, true,
-								   SnapshotSelf, 1, &akey);
-
-		while (HeapTupleIsValid(atup = systable_getnext(ascan)))
-		{
-			attForm = (Form_pg_attribute) GETSTRUCT(atup);
-
-			resetStringInfo(&audit_name);
-			appendStringInfo(&audit_name, "%s.%s.%s",
-							 quote_identifier(nsp_name),
-							 quote_identifier(NameStr(classForm->relname)),
-							 quote_identifier(NameStr(attForm->attname)));
-
-			ccontext = sepgsql_compute_create(scontext,
-											  rcontext,
-											  SEPG_CLASS_DB_COLUMN,
-											  NameStr(attForm->attname));
-
-			/*
-			 * check db_column:{create} permission
-			 */
-			sepgsql_avc_check_perms_label(ccontext,
-										  SEPG_CLASS_DB_COLUMN,
-										  SEPG_DB_COLUMN__CREATE,
-										  audit_name.data,
-										  true);
-
-			object.classId = RelationRelationId;
-			object.objectId = relOid;
-			object.objectSubId = attForm->attnum;
-			SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
-
-			pfree(ccontext);
-		}
-		systable_endscan(ascan);
-		table_close(arel, AccessShareLock);
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				Relation	arel;
+				ScanKeyData akey;
+				SysScanDesc ascan;
+				HeapTuple	atup;
+				Form_pg_attribute attForm;
+
+				arel = table_open(AttributeRelationId, AccessShareLock);
+
+				ScanKeyInit(&akey,
+							Anum_pg_attribute_attrelid,
+							BTEqualStrategyNumber, F_OIDEQ,
+							ObjectIdGetDatum(relOid));
+
+				ascan = systable_beginscan(arel, AttributeRelidNumIndexId, true,
+										   SnapshotSelf, 1, &akey);
+
+				while (HeapTupleIsValid(atup = systable_getnext(ascan)))
+				{
+					attForm = (Form_pg_attribute) GETSTRUCT(atup);
+
+					resetStringInfo(&audit_name);
+					appendStringInfo(&audit_name, "%s.%s.%s",
+									 quote_identifier(nsp_name),
+									 quote_identifier(NameStr(classForm->relname)),
+									 quote_identifier(NameStr(attForm->attname)));
+
+					ccontext = sepgsql_compute_create(scontext,
+													  rcontext,
+													  SEPG_CLASS_DB_COLUMN,
+													  NameStr(attForm->attname));
+
+					/*
+					 * check db_column:{create} permission
+					 */
+					sepgsql_avc_check_perms_label(ccontext,
+												  SEPG_CLASS_DB_COLUMN,
+												  SEPG_DB_COLUMN__CREATE,
+												  audit_name.data,
+												  true);
+
+					object.classId = RelationRelationId;
+					object.objectId = relOid;
+					object.objectSubId = attForm->attnum;
+					SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
+
+					pfree(ccontext);
+				}
+				systable_endscan(ascan);
+				table_close(arel, AccessShareLock);
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
+
 	pfree(rcontext);
 
 out:
@@ -421,7 +523,7 @@ sepgsql_relation_drop(Oid relOid)
 	uint16_t	tclass = 0;
 	char		relkind = get_rel_relkind(relOid);
 
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -439,6 +541,12 @@ sepgsql_relation_drop(Oid relOid)
 				return;
 			/* other indexes are handled specially below; no need for tclass */
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			/* ignore other relkinds */
 			return;
@@ -460,10 +568,23 @@ sepgsql_relation_drop(Oid relOid)
 	pfree(audit_name);
 
 	/* deal with indexes specially */
-	if (relkind == RELKIND_INDEX)
+	switch ((RelKind) relkind)
 	{
-		sepgsql_index_modify(relOid);
-		return;
+		case RELKIND_INDEX:
+			sepgsql_index_modify(relOid);
+			return;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -484,35 +605,51 @@ sepgsql_relation_drop(Oid relOid)
 	/*
 	 * check db_column:{drop} permission
 	 */
-	if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) relkind)
 	{
-		Form_pg_attribute attForm;
-		CatCList   *attrList;
-		HeapTuple	atttup;
-		int			i;
-
-		attrList = SearchSysCacheList1(ATTNUM, ObjectIdGetDatum(relOid));
-		for (i = 0; i < attrList->n_members; i++)
-		{
-			atttup = &attrList->members[i]->tuple;
-			attForm = (Form_pg_attribute) GETSTRUCT(atttup);
-
-			if (attForm->attisdropped)
-				continue;
-
-			object.classId = RelationRelationId;
-			object.objectId = relOid;
-			object.objectSubId = attForm->attnum;
-			audit_name = getObjectIdentity(&object);
-
-			sepgsql_avc_check_perms(&object,
-									SEPG_CLASS_DB_COLUMN,
-									SEPG_DB_COLUMN__DROP,
-									audit_name,
-									true);
-			pfree(audit_name);
-		}
-		ReleaseCatCacheList(attrList);
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				Form_pg_attribute attForm;
+				CatCList   *attrList;
+				HeapTuple	atttup;
+				int			i;
+
+				attrList = SearchSysCacheList1(ATTNUM, ObjectIdGetDatum(relOid));
+				for (i = 0; i < attrList->n_members; i++)
+				{
+					atttup = &attrList->members[i]->tuple;
+					attForm = (Form_pg_attribute) GETSTRUCT(atttup);
+
+					if (attForm->attisdropped)
+						continue;
+
+					object.classId = RelationRelationId;
+					object.objectId = relOid;
+					object.objectSubId = attForm->attnum;
+					audit_name = getObjectIdentity(&object);
+
+					sepgsql_avc_check_perms(&object,
+											SEPG_CLASS_DB_COLUMN,
+											SEPG_DB_COLUMN__DROP,
+											audit_name,
+											true);
+					pfree(audit_name);
+				}
+				ReleaseCatCacheList(attrList);
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 }
 
@@ -529,12 +666,21 @@ sepgsql_relation_truncate(Oid relOid)
 	uint16_t	tclass = 0;
 	char		relkind = get_rel_relkind(relOid);
 
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
 			tclass = SEPG_CLASS_DB_TABLE;
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* ignore other relkinds */
 			return;
@@ -569,17 +715,32 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
 	char		relkind = get_rel_relkind(relOid);
 	uint16_t	tclass = 0;
 
-	if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
-		tclass = SEPG_CLASS_DB_TABLE;
-	else if (relkind == RELKIND_SEQUENCE)
-		tclass = SEPG_CLASS_DB_SEQUENCE;
-	else if (relkind == RELKIND_VIEW)
-		tclass = SEPG_CLASS_DB_VIEW;
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot set security labels on relations except "
-						"for tables, sequences or views")));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			tclass = SEPG_CLASS_DB_TABLE;
+			break;
+		case RELKIND_SEQUENCE:
+			tclass = SEPG_CLASS_DB_SEQUENCE;
+			break;
+		case RELKIND_VIEW:
+			tclass = SEPG_CLASS_DB_VIEW;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot set security labels on relations except "
+							"for tables, sequences or views")));
+			break;
+	}
 
 	object.classId = RelationRelationId;
 	object.objectId = relOid;
@@ -626,7 +787,7 @@ sepgsql_relation_setattr(Oid relOid)
 	char	   *audit_name;
 	uint16_t	tclass;
 
-	switch (get_rel_relkind(relOid))
+	switch ((RelKind) get_rel_relkind(relOid))
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -642,6 +803,12 @@ sepgsql_relation_setattr(Oid relOid)
 			/* deal with indexes specially */
 			sepgsql_index_modify(relOid);
 			return;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			/* other relkinds don't need additional work */
 			return;
diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c
index 92bdf71356..e07f8be8e3 100644
--- a/contrib/vacuumlo/vacuumlo.c
+++ b/contrib/vacuumlo/vacuumlo.c
@@ -203,7 +203,7 @@ vacuumlo(const char *database, const struct _param *param)
 	strcat(buf, "      AND a.atttypid = t.oid ");
 	strcat(buf, "      AND c.relnamespace = s.oid ");
 	strcat(buf, "      AND t.typname in ('oid', 'lo') ");
-	strcat(buf, "      AND c.relkind in (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_MATVIEW) ")");
+	strcat(buf, "      AND c.relkind in (" RelKindAsString(RELKIND_RELATION) ", " RelKindAsString(RELKIND_MATVIEW) ")");
 	strcat(buf, "      AND s.nspname !~ '^pg_'");
 	res = PQexec(conn, buf);
 	if (PQresultStatus(res) != PGRES_TUPLES_OK)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 8ccc228a8c..d16e401060 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1372,7 +1372,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 	classForm = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* Parse into appropriate format; don't error out here */
-	switch (classForm->relkind)
+	switch ((RelKind) classForm->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
@@ -1392,6 +1392,9 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_FOREIGN_TABLE:
 			options = NULL;
 			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_NULL:
 		default:
 			Assert(false);		/* can't get here */
 			options = NULL;		/* keep compiler quiet */
@@ -1997,7 +2000,7 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
 {
 	StdRdOptions *rdopts;
 
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_TOASTVALUE:
 			rdopts = (StdRdOptions *)
@@ -2013,13 +2016,21 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
 			return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* other relkinds are not supported */
 			return NULL;
 	}
+	return NULL;				/* keep compiler happy */
 }
 
-
 /*
  * Parse options for indexes.
  *
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 537913d1bb..d6f91d5f93 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2040,17 +2040,28 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid,
 	 * If the new tuple is too big for storage or contains already toasted
 	 * out-of-line attributes from some other relation, invoke the toaster.
 	 */
-	if (relation->rd_rel->relkind != RELKIND_RELATION &&
-		relation->rd_rel->relkind != RELKIND_MATVIEW)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		/* toast table entries should never be recursively toasted */
-		Assert(!HeapTupleHasExternal(tup));
-		return tup;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
+				return heap_toast_insert_or_update(relation, tup, NULL, options);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			/* toast table entries should never be recursively toasted */
+			Assert(!HeapTupleHasExternal(tup));
+			break;
 	}
-	else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
-		return heap_toast_insert_or_update(relation, tup, NULL, options);
-	else
-		return tup;
+	return tup;
 }
 
 /*
@@ -2773,14 +2784,27 @@ l1:
 	 * because we need to look at the contents of the tuple, but it's OK to
 	 * release the content lock on the buffer first.
 	 */
-	if (relation->rd_rel->relkind != RELKIND_RELATION &&
-		relation->rd_rel->relkind != RELKIND_MATVIEW)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		/* toast table entries should never be recursively toasted */
-		Assert(!HeapTupleHasExternal(&tp));
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			if (HeapTupleHasExternal(&tp))
+				heap_toast_delete(relation, &tp, false);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			/* toast table entries should never be recursively toasted */
+			Assert(!HeapTupleHasExternal(&tp));
+			break;
 	}
-	else if (HeapTupleHasExternal(&tp))
-		heap_toast_delete(relation, &tp, false);
 
 	/*
 	 * Mark tuple for invalidation from system caches at next command
@@ -3362,18 +3386,30 @@ l2:
 	 * We need to invoke the toaster if there are already any out-of-line
 	 * toasted values present, or if the new tuple is over-threshold.
 	 */
-	if (relation->rd_rel->relkind != RELKIND_RELATION &&
-		relation->rd_rel->relkind != RELKIND_MATVIEW)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		/* toast table entries should never be recursively toasted */
-		Assert(!HeapTupleHasExternal(&oldtup));
-		Assert(!HeapTupleHasExternal(newtup));
-		need_toast = false;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			need_toast = (HeapTupleHasExternal(&oldtup) ||
+						  HeapTupleHasExternal(newtup) ||
+						  newtup->t_len > TOAST_TUPLE_THRESHOLD);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			/* toast table entries should never be recursively toasted */
+			Assert(!HeapTupleHasExternal(&oldtup));
+			Assert(!HeapTupleHasExternal(newtup));
+			need_toast = false;
+			break;
 	}
-	else
-		need_toast = (HeapTupleHasExternal(&oldtup) ||
-					  HeapTupleHasExternal(newtup) ||
-					  newtup->t_len > TOAST_TUPLE_THRESHOLD);
 
 	pagefree = PageGetHeapFreeSpace(page);
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 56b35622f1..ba2ef7d45d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -600,12 +600,27 @@ heapam_relation_set_new_filenode(Relation rel,
 	 */
 	if (persistence == RELPERSISTENCE_UNLOGGED)
 	{
-		Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-			   rel->rd_rel->relkind == RELKIND_MATVIEW ||
-			   rel->rd_rel->relkind == RELKIND_TOASTVALUE);
-		smgrcreate(srel, INIT_FORKNUM, false);
-		log_smgrcreate(newrnode, INIT_FORKNUM);
-		smgrimmedsync(srel, INIT_FORKNUM);
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+				smgrcreate(srel, INIT_FORKNUM, false);
+				log_smgrcreate(newrnode, INIT_FORKNUM);
+				smgrimmedsync(srel, INIT_FORKNUM);
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				Assert(false);
+				break;
+		}
 	}
 
 	smgrclose(srel);
diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index 584f101dd9..2d442aa2f0 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -50,8 +50,24 @@ heap_toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)
 	 * We should only ever be called for tuples of plain relations or
 	 * materialized views --- recursing on a toast rel is bad news.
 	 */
-	Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-		   rel->rd_rel->relkind == RELKIND_MATVIEW);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			Assert(false);
+			break;
+	}
 
 	/*
 	 * Get the tuple descriptor and break down the tuple into fields.
@@ -122,8 +138,24 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 	 * We should only ever be called for tuples of plain relations or
 	 * materialized views --- recursing on a toast rel is bad news.
 	 */
-	Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-		   rel->rd_rel->relkind == RELKIND_MATVIEW);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			Assert(false);
+			break;
+	}
 
 	/*
 	 * Get the tuple descriptor and break down the tuple(s) into fields.
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 6b9750c244..f830ef7951 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -135,12 +135,28 @@ index_open(Oid relationId, LOCKMODE lockmode)
 
 	r = relation_open(relationId, lockmode);
 
-	if (r->rd_rel->relkind != RELKIND_INDEX &&
-		r->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not an index",
-						RelationGetRelationName(r))));
+	switch ((RelKind) r->rd_rel->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not an index",
+							RelationGetRelationName(r))));
+			break;
+	}
 
 	return r;
 }
diff --git a/src/backend/access/table/table.c b/src/backend/access/table/table.c
index 1aa01a54b3..fde36e8477 100644
--- a/src/backend/access/table/table.c
+++ b/src/backend/access/table/table.c
@@ -42,17 +42,32 @@ table_open(Oid relationId, LOCKMODE lockmode)
 
 	r = relation_open(relationId, lockmode);
 
-	if (r->rd_rel->relkind == RELKIND_INDEX ||
-		r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is an index",
-						RelationGetRelationName(r))));
-	else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is a composite type",
-						RelationGetRelationName(r))));
+	switch ((RelKind) r->rd_rel->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is an index",
+							RelationGetRelationName(r))));
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is a composite type",
+							RelationGetRelationName(r))));
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	return r;
 }
@@ -71,17 +86,32 @@ table_openrv(const RangeVar *relation, LOCKMODE lockmode)
 
 	r = relation_openrv(relation, lockmode);
 
-	if (r->rd_rel->relkind == RELKIND_INDEX ||
-		r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is an index",
-						RelationGetRelationName(r))));
-	else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is a composite type",
-						RelationGetRelationName(r))));
+	switch ((RelKind) r->rd_rel->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is an index",
+							RelationGetRelationName(r))));
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is a composite type",
+							RelationGetRelationName(r))));
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	return r;
 }
@@ -104,17 +134,32 @@ table_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
 
 	if (r)
 	{
-		if (r->rd_rel->relkind == RELKIND_INDEX ||
-			r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is an index",
-							RelationGetRelationName(r))));
-		else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a composite type",
-							RelationGetRelationName(r))));
+		switch ((RelKind) r->rd_rel->relkind)
+		{
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is an index",
+								RelationGetRelationName(r))));
+				break;
+			case RELKIND_COMPOSITE_TYPE:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is a composite type",
+								RelationGetRelationName(r))));
+				break;
+			case RELKIND_SEQUENCE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 	}
 
 	return r;
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 4b2bb29559..e4a11ddd64 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -47,28 +47,42 @@ table_slot_callbacks(Relation relation)
 
 	if (relation->rd_tableam)
 		tts_cb = relation->rd_tableam->slot_callbacks(relation);
-	else if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-	{
-		/*
-		 * Historically FDWs expect to store heap tuples in slots. Continue
-		 * handing them one, to make it less painful to adapt FDWs to new
-		 * versions. The cost of a heap slot over a virtual slot is pretty
-		 * small.
-		 */
-		tts_cb = &TTSOpsHeapTuple;
-	}
 	else
-	{
-		/*
-		 * These need to be supported, as some parts of the code (like COPY)
-		 * need to create slots for such relations too. It seems better to
-		 * centralize the knowledge that a heap slot is the right thing in
-		 * that case here.
-		 */
-		Assert(relation->rd_rel->relkind == RELKIND_VIEW ||
-			   relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
-		tts_cb = &TTSOpsVirtual;
-	}
+		switch ((RelKind) relation->rd_rel->relkind)
+		{
+			case RELKIND_FOREIGN_TABLE:
+
+				/*
+				 * Historically FDWs expect to store heap tuples in slots.
+				 * Continue handing them one, to make it less painful to adapt
+				 * FDWs to new versions. The cost of a heap slot over a
+				 * virtual slot is pretty small.
+				 */
+				tts_cb = &TTSOpsHeapTuple;
+				break;
+			case RELKIND_VIEW:
+			case RELKIND_PARTITIONED_TABLE:
+
+				/*
+				 * These need to be supported, as some parts of the code (like
+				 * COPY) need to create slots for such relations too. It seems
+				 * better to centralize the knowledge that a heap slot is the
+				 * right thing in that case here.
+				 */
+				tts_cb = &TTSOpsVirtual;
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				Assert(false);
+				break;
+		}
 
 	return tts_cb;
 }
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index c626161408..a80e759a80 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -1765,36 +1765,65 @@ ExecGrant_Relation(InternalGrant *istmt)
 			elog(ERROR, "cache lookup failed for relation %u", relOid);
 		pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
 
-		/* Not sensible to grant on an index */
-		if (pg_class_tuple->relkind == RELKIND_INDEX ||
-			pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is an index",
-							NameStr(pg_class_tuple->relname))));
+		switch ((RelKind) pg_class_tuple->relkind)
+		{
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+				/* Not sensible to grant on an index */
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is an index",
+								NameStr(pg_class_tuple->relname))));
 
-		/* Composite types aren't tables either */
-		if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a composite type",
-							NameStr(pg_class_tuple->relname))));
+			case RELKIND_COMPOSITE_TYPE:
+				/* Composite types aren't tables either */
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is a composite type",
+								NameStr(pg_class_tuple->relname))));
+
+			case RELKIND_SEQUENCE:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				/* Used GRANT SEQUENCE on a non-sequence? */
+				if (istmt->objtype == OBJECT_SEQUENCE)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a sequence",
+									NameStr(pg_class_tuple->relname))));
+				break;
+		}
 
-		/* Used GRANT SEQUENCE on a non-sequence? */
-		if (istmt->objtype == OBJECT_SEQUENCE &&
-			pg_class_tuple->relkind != RELKIND_SEQUENCE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is not a sequence",
-							NameStr(pg_class_tuple->relname))));
 
 		/* Adjust the default permissions based on object type */
 		if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
 		{
-			if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
-				this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
-			else
-				this_privileges = ACL_ALL_RIGHTS_RELATION;
+			switch ((RelKind) pg_class_tuple->relkind)
+			{
+				case RELKIND_SEQUENCE:
+					this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+					break;
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					this_privileges = ACL_ALL_RIGHTS_RELATION;
+					break;
+			}
 		}
 		else
 			this_privileges = istmt->privileges;
@@ -1807,42 +1836,54 @@ ExecGrant_Relation(InternalGrant *istmt)
 		 */
 		if (istmt->objtype == OBJECT_TABLE)
 		{
-			if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
+			switch ((RelKind) pg_class_tuple->relkind)
 			{
-				/*
-				 * For backward compatibility, just throw a warning for
-				 * invalid sequence permissions when using the non-sequence
-				 * GRANT syntax.
-				 */
-				if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
-				{
-					/*
-					 * Mention the object name because the user needs to know
-					 * which operations succeeded.  This is required because
-					 * WARNING allows the command to continue.
-					 */
-					ereport(WARNING,
-							(errcode(ERRCODE_INVALID_GRANT_OPERATION),
-							 errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
-									NameStr(pg_class_tuple->relname))));
-					this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
-				}
-			}
-			else
-			{
-				if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
-				{
+				case RELKIND_SEQUENCE:
+
 					/*
-					 * USAGE is the only permission supported by sequences but
-					 * not by non-sequences.  Don't mention the object name
-					 * because we didn't in the combined TABLE | SEQUENCE
-					 * check.
+					 * For backward compatibility, just throw a warning for
+					 * invalid sequence permissions when using the
+					 * non-sequence GRANT syntax.
 					 */
-					ereport(ERROR,
-							(errcode(ERRCODE_INVALID_GRANT_OPERATION),
-							 errmsg("invalid privilege type %s for table",
-									"USAGE")));
-				}
+					if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
+					{
+						/*
+						 * Mention the object name because the user needs to
+						 * know which operations succeeded.  This is required
+						 * because WARNING allows the command to continue.
+						 */
+						ereport(WARNING,
+								(errcode(ERRCODE_INVALID_GRANT_OPERATION),
+								 errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
+										NameStr(pg_class_tuple->relname))));
+						this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
+					}
+					break;
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
+					{
+						/*
+						 * USAGE is the only permission supported by sequences
+						 * but not by non-sequences.  Don't mention the object
+						 * name because we didn't in the combined TABLE |
+						 * SEQUENCE check.
+						 */
+						ereport(ERROR,
+								(errcode(ERRCODE_INVALID_GRANT_OPERATION),
+								 errmsg("invalid privilege type %s for table",
+										"USAGE")));
+					}
+					break;
 			}
 		}
 
@@ -1881,12 +1922,21 @@ ExecGrant_Relation(InternalGrant *istmt)
 								   &isNull);
 		if (isNull)
 		{
-			switch (pg_class_tuple->relkind)
+			switch ((RelKind) pg_class_tuple->relkind)
 			{
 				case RELKIND_SEQUENCE:
 					old_acl = acldefault(OBJECT_SEQUENCE, ownerId);
 					break;
-				default:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
 					old_acl = acldefault(OBJECT_TABLE, ownerId);
 					break;
 			}
@@ -1925,11 +1975,21 @@ ExecGrant_Relation(InternalGrant *istmt)
 								old_acl, ownerId,
 								&grantorId, &avail_goptions);
 
-			switch (pg_class_tuple->relkind)
+			switch ((RelKind) pg_class_tuple->relkind)
 			{
 				case RELKIND_SEQUENCE:
 					objtype = OBJECT_SEQUENCE;
 					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
 				default:
 					objtype = OBJECT_TABLE;
 					break;
@@ -2009,20 +2069,36 @@ ExecGrant_Relation(InternalGrant *istmt)
 						 errmsg("invalid privilege type %s for column",
 								privilege_to_string(this_privileges))));
 
-			if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
-				this_privileges & ~((AclMode) ACL_SELECT))
+			switch ((RelKind) pg_class_tuple->relkind)
 			{
-				/*
-				 * The only column privilege allowed on sequences is SELECT.
-				 * This is a warning not error because we do it that way for
-				 * relation-level privileges.
-				 */
-				ereport(WARNING,
-						(errcode(ERRCODE_INVALID_GRANT_OPERATION),
-						 errmsg("sequence \"%s\" only supports SELECT column privileges",
-								NameStr(pg_class_tuple->relname))));
+				case RELKIND_SEQUENCE:
+					if (this_privileges & ~((AclMode) ACL_SELECT))
+					{
+						/*
+						 * The only column privilege allowed on sequences is
+						 * SELECT. This is a warning not error because we do
+						 * it that way for relation-level privileges.
+						 */
+						ereport(WARNING,
+								(errcode(ERRCODE_INVALID_GRANT_OPERATION),
+								 errmsg("sequence \"%s\" only supports SELECT column privileges",
+										NameStr(pg_class_tuple->relname))));
 
-				this_privileges &= (AclMode) ACL_SELECT;
+						this_privileges &= (AclMode) ACL_SELECT;
+					}
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 
 			expand_col_privileges(col_privs->cols, relOid,
@@ -3824,11 +3900,21 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
 	if (isNull)
 	{
 		/* No ACL, so build default ACL */
-		switch (classForm->relkind)
+		switch ((RelKind) classForm->relkind)
 		{
 			case RELKIND_SEQUENCE:
 				acl = acldefault(OBJECT_SEQUENCE, ownerId);
 				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
 			default:
 				acl = acldefault(OBJECT_TABLE, ownerId);
 				break;
@@ -5519,58 +5605,85 @@ recordExtObjInitPriv(Oid objoid, Oid classoid)
 		 * composite types.  (These cases are unreachable given the
 		 * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
 		 */
-		if (pg_class_tuple->relkind == RELKIND_INDEX ||
-			pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
-			pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+		switch ((RelKind) pg_class_tuple->relkind)
 		{
-			ReleaseSysCache(tuple);
-			return;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+				ReleaseSysCache(tuple);
+				return;
+			case RELKIND_SEQUENCE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/*
 		 * If this isn't a sequence then it's possibly going to have
 		 * column-level ACLs associated with it.
 		 */
-		if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+		switch ((RelKind) pg_class_tuple->relkind)
 		{
-			AttrNumber	curr_att;
-			AttrNumber	nattrs = pg_class_tuple->relnatts;
-
-			for (curr_att = 1; curr_att <= nattrs; curr_att++)
-			{
-				HeapTuple	attTuple;
-				Datum		attaclDatum;
-
-				attTuple = SearchSysCache2(ATTNUM,
-										   ObjectIdGetDatum(objoid),
-										   Int16GetDatum(curr_att));
-
-				if (!HeapTupleIsValid(attTuple))
-					continue;
-
-				/* ignore dropped columns */
-				if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
+			case RELKIND_SEQUENCE:
+				break;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
 				{
-					ReleaseSysCache(attTuple);
-					continue;
-				}
-
-				attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
-											  Anum_pg_attribute_attacl,
-											  &isNull);
+					AttrNumber	curr_att;
+					AttrNumber	nattrs = pg_class_tuple->relnatts;
 
-				/* no need to do anything for a NULL ACL */
-				if (isNull)
-				{
-					ReleaseSysCache(attTuple);
-					continue;
+					for (curr_att = 1; curr_att <= nattrs; curr_att++)
+					{
+						HeapTuple	attTuple;
+						Datum		attaclDatum;
+
+						attTuple = SearchSysCache2(ATTNUM,
+												   ObjectIdGetDatum(objoid),
+												   Int16GetDatum(curr_att));
+
+						if (!HeapTupleIsValid(attTuple))
+							continue;
+
+						/* ignore dropped columns */
+						if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
+						{
+							ReleaseSysCache(attTuple);
+							continue;
+						}
+
+						attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
+													  Anum_pg_attribute_attacl,
+													  &isNull);
+
+						/* no need to do anything for a NULL ACL */
+						if (isNull)
+						{
+							ReleaseSysCache(attTuple);
+							continue;
+						}
+
+						recordExtensionInitPrivWorker(objoid, classoid, curr_att,
+													  DatumGetAclP(attaclDatum));
+
+						ReleaseSysCache(attTuple);
+					}
 				}
-
-				recordExtensionInitPrivWorker(objoid, classoid, curr_att,
-											  DatumGetAclP(attaclDatum));
-
-				ReleaseSysCache(attTuple);
-			}
+				break;
 		}
 
 		aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
@@ -5813,40 +5926,70 @@ removeExtObjInitPriv(Oid objoid, Oid classoid)
 		 * composite types.  (These cases are unreachable given the
 		 * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
 		 */
-		if (pg_class_tuple->relkind == RELKIND_INDEX ||
-			pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
-			pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+		switch ((RelKind) pg_class_tuple->relkind)
 		{
-			ReleaseSysCache(tuple);
-			return;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+				ReleaseSysCache(tuple);
+				return;
+			case RELKIND_SEQUENCE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/*
 		 * If this isn't a sequence then it's possibly going to have
 		 * column-level ACLs associated with it.
 		 */
-		if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+		switch ((RelKind) pg_class_tuple->relkind)
 		{
-			AttrNumber	curr_att;
-			AttrNumber	nattrs = pg_class_tuple->relnatts;
+			case RELKIND_SEQUENCE:
+				break;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				{
+					AttrNumber	curr_att;
+					AttrNumber	nattrs = pg_class_tuple->relnatts;
 
-			for (curr_att = 1; curr_att <= nattrs; curr_att++)
-			{
-				HeapTuple	attTuple;
+					for (curr_att = 1; curr_att <= nattrs; curr_att++)
+					{
+						HeapTuple	attTuple;
 
-				attTuple = SearchSysCache2(ATTNUM,
-										   ObjectIdGetDatum(objoid),
-										   Int16GetDatum(curr_att));
+						attTuple = SearchSysCache2(ATTNUM,
+												   ObjectIdGetDatum(objoid),
+												   Int16GetDatum(curr_att));
 
-				if (!HeapTupleIsValid(attTuple))
-					continue;
+						if (!HeapTupleIsValid(attTuple))
+							continue;
 
-				/* when removing, remove all entries, even dropped columns */
+						/*
+						 * when removing, remove all entries, even dropped
+						 * columns
+						 */
 
-				recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
+						recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
 
-				ReleaseSysCache(attTuple);
-			}
+						ReleaseSysCache(attTuple);
+					}
+				}
+				break;
 		}
 
 		ReleaseSysCache(tuple);
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index b33a2f94af..51af304fa6 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1395,22 +1395,36 @@ doDeletion(const ObjectAddress *object, int flags)
 			{
 				char		relKind = get_rel_relkind(object->objectId);
 
-				if (relKind == RELKIND_INDEX ||
-					relKind == RELKIND_PARTITIONED_INDEX)
+				switch ((RelKind) relKind)
 				{
-					bool		concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
-					bool		concurrent_lock_mode = ((flags & PERFORM_DELETION_CONCURRENT_LOCK) != 0);
-
-					Assert(object->objectSubId == 0);
-					index_drop(object->objectId, concurrent, concurrent_lock_mode);
-				}
-				else
-				{
-					if (object->objectSubId != 0)
-						RemoveAttributeById(object->objectId,
-											object->objectSubId);
-					else
-						heap_drop_with_catalog(object->objectId);
+					case RELKIND_INDEX:
+					case RELKIND_PARTITIONED_INDEX:
+						{
+							bool		concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
+							bool		concurrent_lock_mode = ((flags & PERFORM_DELETION_CONCURRENT_LOCK) != 0);
+
+							Assert(object->objectSubId == 0);
+							index_drop(object->objectId, concurrent, concurrent_lock_mode);
+						}
+						break;
+					case RELKIND_SEQUENCE:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_FOREIGN_TABLE:
+					case RELKIND_MATVIEW:
+					case RELKIND_PARTITIONED_TABLE:
+					case RELKIND_RELATION:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_VIEW:
+					case RELKIND_NULL:
+					default:
+						{
+							if (object->objectSubId != 0)
+								RemoveAttributeById(object->objectId,
+													object->objectSubId);
+							else
+								heap_drop_with_catalog(object->objectId);
+						}
+						break;
 				}
 
 				/*
@@ -1419,8 +1433,8 @@ doDeletion(const ObjectAddress *object, int flags)
 				 */
 				if (relKind == RELKIND_SEQUENCE)
 					DeleteSequenceTuple(object->objectId);
-				break;
 			}
+			break;
 
 		case OCLASS_PROC:
 			RemoveFunctionById(object->objectId);
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 3c83fe6bab..9af088b47c 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -335,7 +335,7 @@ heap_create(const char *relname,
 	*relminmxid = InvalidMultiXactId;
 
 	/* Handle reltablespace for specific relkinds. */
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_VIEW:
 		case RELKIND_COMPOSITE_TYPE:
@@ -360,6 +360,14 @@ heap_create(const char *relname,
 			 */
 			reltablespace = InvalidOid;
 			break;
+
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			break;
 	}
@@ -415,21 +423,12 @@ heap_create(const char *relname,
 	{
 		RelationOpenSmgr(rel);
 
-		switch (rel->rd_rel->relkind)
+		switch ((RelKind) 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:
@@ -437,6 +436,14 @@ heap_create(const char *relname,
 												relpersistence,
 												relfrozenxid, relminmxid);
 				break;
+			case RELKIND_VIEW:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_NULL:
+			default:
+				Assert(false);
 		}
 	}
 
@@ -506,18 +513,32 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
 	 * Skip this for a view or type relation, since those don't have system
 	 * attributes.
 	 */
-	if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
+	switch ((RelKind) relkind)
 	{
-		for (i = 0; i < natts; i++)
-		{
-			Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
+		case RELKIND_VIEW:
+		case RELKIND_COMPOSITE_TYPE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			for (i = 0; i < natts; i++)
+			{
+				Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
 
-			if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
-				ereport(ERROR,
-						(errcode(ERRCODE_DUPLICATE_COLUMN),
-						 errmsg("column name \"%s\" conflicts with a system column name",
-								NameStr(attr->attname))));
-		}
+				if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
+					ereport(ERROR,
+							(errcode(ERRCODE_DUPLICATE_COLUMN),
+							 errmsg("column name \"%s\" conflicts with a system column name",
+									NameStr(attr->attname))));
+			}
+			break;
 	}
 
 	/*
@@ -842,19 +863,33 @@ AddNewAttributeTuples(Oid new_rel_oid,
 	 * all for a view or type relation.  We don't bother with making datatype
 	 * dependencies here, since presumably all these types are pinned.
 	 */
-	if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
+	switch ((RelKind) relkind)
 	{
-		for (i = 0; i < (int) lengthof(SysAtt); i++)
-		{
-			FormData_pg_attribute attStruct;
+		case RELKIND_VIEW:
+		case RELKIND_COMPOSITE_TYPE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			for (i = 0; i < (int) lengthof(SysAtt); i++)
+			{
+				FormData_pg_attribute attStruct;
 
-			memcpy(&attStruct, SysAtt[i], sizeof(FormData_pg_attribute));
+				memcpy(&attStruct, SysAtt[i], sizeof(FormData_pg_attribute));
 
-			/* Fill in the correct relation OID in the copied tuple */
-			attStruct.attrelid = new_rel_oid;
+				/* Fill in the correct relation OID in the copied tuple */
+				attStruct.attrelid = new_rel_oid;
 
-			InsertPgAttributeTuple(rel, &attStruct, (Datum) 0, indstate);
-		}
+				InsertPgAttributeTuple(rel, &attStruct, (Datum) 0, indstate);
+			}
+			break;
 	}
 
 	/*
@@ -972,7 +1007,7 @@ AddNewRelationTuple(Relation pg_class_desc,
 	 */
 	new_rel_reltup = new_rel_desc->rd_rel;
 
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
@@ -989,6 +1024,12 @@ AddNewRelationTuple(Relation pg_class_desc,
 			new_rel_reltup->reltuples = 1;
 			new_rel_reltup->relallvisible = 0;
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* Views, etc, have no disk storage */
 			new_rel_reltup->relpages = 0;
@@ -1221,7 +1262,7 @@ heap_create_with_catalog(const char *relname,
 	 */
 	if (use_user_acl)
 	{
-		switch (relkind)
+		switch ((RelKind) relkind)
 		{
 			case RELKIND_RELATION:
 			case RELKIND_VIEW:
@@ -1235,6 +1276,11 @@ heap_create_with_catalog(const char *relname,
 				relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
 											  relnamespace);
 				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
 			default:
 				relacl = NULL;
 				break;
@@ -1273,13 +1319,27 @@ heap_create_with_catalog(const char *relname,
 	 * during initdb). We do not create them where the use of a relation as
 	 * such is an implementation detail: toast tables, sequences and indexes.
 	 */
-	if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
-							  relkind == RELKIND_VIEW ||
-							  relkind == RELKIND_MATVIEW ||
-							  relkind == RELKIND_FOREIGN_TABLE ||
-							  relkind == RELKIND_COMPOSITE_TYPE ||
-							  relkind == RELKIND_PARTITIONED_TABLE))
-		new_array_oid = AssignTypeArrayOid();
+	if (IsUnderPostmaster)
+	{
+		switch ((RelKind) relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_VIEW:
+			case RELKIND_MATVIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_PARTITIONED_TABLE:
+				new_array_oid = AssignTypeArrayOid();
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
+	}
 
 	/*
 	 * Since defining a relation also defines a complex type, we add a new
@@ -1385,51 +1445,67 @@ heap_create_with_catalog(const char *relname,
 	 * Also, skip this in bootstrap mode, since we don't make dependencies
 	 * while bootstrapping.
 	 */
-	if (relkind != RELKIND_COMPOSITE_TYPE &&
-		relkind != RELKIND_TOASTVALUE &&
-		!IsBootstrapProcessingMode())
+	switch ((RelKind) relkind)
 	{
-		ObjectAddress myself,
-					referenced;
-
-		myself.classId = RelationRelationId;
-		myself.objectId = relid;
-		myself.objectSubId = 0;
-
-		referenced.classId = NamespaceRelationId;
-		referenced.objectId = relnamespace;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-
-		recordDependencyOnOwner(RelationRelationId, relid, ownerid);
-
-		recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
-
-		recordDependencyOnCurrentExtension(&myself, false);
-
-		if (reloftypeid)
-		{
-			referenced.classId = TypeRelationId;
-			referenced.objectId = reloftypeid;
-			referenced.objectSubId = 0;
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-		}
-
-		/*
-		 * Make a dependency link to force the relation to be deleted if its
-		 * access method is. Do this only for relation and materialized views.
-		 *
-		 * 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)
-		{
-			referenced.classId = AccessMethodRelationId;
-			referenced.objectId = accessmtd;
-			referenced.objectSubId = 0;
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-		}
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_TOASTVALUE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			if (!IsBootstrapProcessingMode())
+			{
+				ObjectAddress myself,
+							referenced;
+
+				myself.classId = RelationRelationId;
+				myself.objectId = relid;
+				myself.objectSubId = 0;
+
+				referenced.classId = NamespaceRelationId;
+				referenced.objectId = relnamespace;
+				referenced.objectSubId = 0;
+				recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+				recordDependencyOnOwner(RelationRelationId, relid, ownerid);
+
+				recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
+
+				recordDependencyOnCurrentExtension(&myself, false);
+
+				if (reloftypeid)
+				{
+					referenced.classId = TypeRelationId;
+					referenced.objectId = reloftypeid;
+					referenced.objectSubId = 0;
+					recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+				}
+
+				/*
+				 * Make a dependency link to force the relation to be deleted
+				 * if its access method is. Do this only for relation and
+				 * materialized views.
+				 *
+				 * 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)
+				{
+					referenced.classId = AccessMethodRelationId;
+					referenced.objectId = accessmtd;
+					referenced.objectSubId = 0;
+					recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+				}
+			}
+			break;
 	}
 
 	/* Post creation hook for new relation */
@@ -2388,12 +2464,28 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr,
 	 * Partitioned tables do not contain any rows themselves, so a NO INHERIT
 	 * constraint makes no sense.
 	 */
-	if (is_no_inherit &&
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-				 errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			if (is_no_inherit)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+						 errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
+								RelationGetRelationName(rel))));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * Create the Check Constraint
@@ -3259,8 +3351,23 @@ heap_truncate_one_rel(Relation rel)
 	 * Truncate the relation.  Partitioned tables have no storage, so there is
 	 * nothing to do for them here.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			return;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/* Truncate the underlying relation */
 	table_relation_nontransactional_truncate(rel);
@@ -3313,9 +3420,26 @@ heap_truncate_check_FKs(List *relations, bool tempTables)
 	{
 		Relation	rel = lfirst(cell);
 
-		if (rel->rd_rel->relhastriggers ||
-			rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			oids = lappend_oid(oids, RelationGetRelid(rel));
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				if (!rel->rd_rel->relhastriggers)
+					break;
+				/* fallthrough */
+			case RELKIND_PARTITIONED_TABLE:
+				oids = lappend_oid(oids, RelationGetRelid(rel));
+				break;
+		}
 	}
 
 	/*
@@ -3538,7 +3662,24 @@ StorePartitionKey(Relation rel,
 	ObjectAddress myself;
 	ObjectAddress referenced;
 
-	Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			Assert(false);
+			break;
+	}
 
 	/* Copy the partition attribute numbers, opclass OIDs into arrays */
 	partattrs_vec = buildint2vector(partattrs, partnatts);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index cdc01c49c9..16b753258d 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2220,8 +2220,24 @@ 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)
-		RelationDropStorage(userIndexRelation);
+	switch ((RelKind) userIndexRelation->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+		case RELKIND_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			RelationDropStorage(userIndexRelation);
+			break;
+	}
 
 	/*
 	 * Close and flush the index's relcache entry, to ensure relcache doesn't
@@ -2748,7 +2764,23 @@ index_update_stats(Relation rel,
 	rd_rel = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* Should this be a more comprehensive test? */
-	Assert(rd_rel->relkind != RELKIND_PARTITIONED_INDEX);
+	switch ((RelKind) rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_INDEX:
+			Assert(false);
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_INDEX:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/* Apply required updates, if any, to copied tuple */
 
@@ -2764,10 +2796,25 @@ index_update_stats(Relation rel,
 		BlockNumber relpages = RelationGetNumberOfBlocks(rel);
 		BlockNumber relallvisible;
 
-		if (rd_rel->relkind != RELKIND_INDEX)
-			visibilitymap_count(rel, &relallvisible, NULL);
-		else					/* don't bother for indexes */
-			relallvisible = 0;
+		switch ((RelKind) rd_rel->relkind)
+		{
+			case RELKIND_INDEX:
+				relallvisible = 0;
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				visibilitymap_count(rel, &relallvisible, NULL);
+				break;
+		}
 
 		if (rd_rel->relpages != (int32) relpages)
 		{
@@ -3478,9 +3525,25 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
 	 * The case of reindexing partitioned tables and indexes is handled
 	 * differently by upper layers, so this case shouldn't arise.
 	 */
-	if (iRel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-		elog(ERROR, "unsupported relation kind for index \"%s\"",
-			 RelationGetRelationName(iRel));
+	switch ((RelKind) iRel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_INDEX:
+			elog(ERROR, "unsupported relation kind for index \"%s\"",
+				 RelationGetRelationName(iRel));
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * Don't allow reindex on temp tables of other backends ... their local
@@ -3694,14 +3757,27 @@ reindex_relation(Oid relid, int flags, int options)
 	 * (REINDEX SCHEMA) and happen to come across a partitioned table.  The
 	 * partitions may be reindexed on their own anyway.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		ereport(WARNING,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
-						RelationGetRelationName(rel))));
-		table_close(rel, ShareLock);
-		return false;
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(WARNING,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
+							RelationGetRelationName(rel))));
+			table_close(rel, ShareLock);
+			return false;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	toast_relid = rel->rd_rel->reltoastrelid;
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 534df8e802..4d8c1ca4c5 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -97,7 +97,8 @@
  */
 typedef struct
 {
-	const char *class_descr;	/* string describing the catalog, for internal error messages */
+	const char *class_descr;	/* string describing the catalog, for internal
+								 * error messages */
 	Oid			class_oid;		/* oid of catalog */
 	Oid			oid_index_oid;	/* oid of index on system oid column */
 	int			oid_catcache_id;	/* id of catcache on system oid column	*/
@@ -1342,48 +1343,136 @@ get_relation_by_qualified_name(ObjectType objtype, List *object,
 	switch (objtype)
 	{
 		case OBJECT_INDEX:
-			if (relation->rd_rel->relkind != RELKIND_INDEX &&
-				relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not an index",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+					break;
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not an index",
+									RelationGetRelationName(relation))));
+			}
 			break;
 		case OBJECT_SEQUENCE:
-			if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a sequence",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_SEQUENCE:
+					break;
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a sequence",
+									RelationGetRelationName(relation))));
+			}
 			break;
 		case OBJECT_TABLE:
-			if (relation->rd_rel->relkind != RELKIND_RELATION &&
-				relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a table",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+					break;
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a table",
+									RelationGetRelationName(relation))));
+			}
 			break;
 		case OBJECT_VIEW:
-			if (relation->rd_rel->relkind != RELKIND_VIEW)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a view",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_VIEW:
+					break;
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a view",
+									RelationGetRelationName(relation))));
+			}
 			break;
 		case OBJECT_MATVIEW:
-			if (relation->rd_rel->relkind != RELKIND_MATVIEW)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a materialized view",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_MATVIEW:
+					break;
+				case RELKIND_VIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a materialized view",
+									RelationGetRelationName(relation))));
+			}
 			break;
 		case OBJECT_FOREIGN_TABLE:
-			if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a foreign table",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_FOREIGN_TABLE:
+					break;
+				case RELKIND_MATVIEW:
+				case RELKIND_VIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a foreign table",
+									RelationGetRelationName(relation))));
+			}
 			break;
 		default:
 			elog(ERROR, "unrecognized objtype: %d", (int) objtype);
@@ -3795,7 +3884,7 @@ getRelationDescription(StringInfo buffer, Oid relid)
 
 	relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
 
-	switch (relForm->relkind)
+	switch ((RelKind) relForm->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -3831,6 +3920,7 @@ getRelationDescription(StringInfo buffer, Oid relid)
 			appendStringInfo(buffer, _("foreign table %s"),
 							 relname);
 			break;
+		case RELKIND_NULL:
 		default:
 			/* shouldn't get here */
 			appendStringInfo(buffer, _("relation %s"),
@@ -4276,7 +4366,7 @@ getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId)
 		elog(ERROR, "cache lookup failed for relation %u", relid);
 	relForm = (Form_pg_class) GETSTRUCT(relTup);
 
-	switch (relForm->relkind)
+	switch ((RelKind) relForm->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -4304,6 +4394,7 @@ getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId)
 		case RELKIND_FOREIGN_TABLE:
 			appendStringInfoString(buffer, "foreign table");
 			break;
+		case RELKIND_NULL:
 		default:
 			/* shouldn't get here */
 			appendStringInfoString(buffer, "relation");
@@ -5451,7 +5542,7 @@ strlist_to_textarray(List *list)
 ObjectType
 get_relkind_objtype(char relkind)
 {
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -5469,6 +5560,8 @@ get_relkind_objtype(char relkind)
 			return OBJECT_FOREIGN_TABLE;
 		case RELKIND_TOASTVALUE:
 			return OBJECT_TABLE;
+		case RELKIND_NULL:
+		case RELKIND_COMPOSITE_TYPE:
 		default:
 			/* Per above, don't raise an error */
 			return OBJECT_TABLE;
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 239ac017fa..65c4b96289 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -235,8 +235,25 @@ has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr)
 	ListCell   *partexprs_item;
 	int			i;
 
-	if (attnums == NULL || rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		return false;
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			if (attnums == NULL)
+				return false;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return false;
+	}
 
 	key = RelationGetPartitionKey(rel);
 	partnatts = get_partition_natts(key);
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 21cfdcace9..2ba55bc6b3 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -837,14 +837,31 @@ getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
 		 * must be what we are looking for.  (We need the relkind test because
 		 * indexes can also have auto dependencies on columns.)
 		 */
-		if (deprec->classid == RelationRelationId &&
-			deprec->objsubid == 0 &&
-			deprec->refobjsubid != 0 &&
-			(deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
-			get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
+		switch ((RelKind) get_rel_relkind(deprec->objid))
 		{
-			if (!deptype || deprec->deptype == deptype)
-				result = lappend_oid(result, deprec->objid);
+			case RELKIND_SEQUENCE:
+				if (deprec->classid == RelationRelationId &&
+					deprec->objsubid == 0 &&
+					deprec->refobjsubid != 0 &&
+					(deprec->deptype == DEPENDENCY_AUTO ||
+					 deprec->deptype == DEPENDENCY_INTERNAL) &&
+					(!deptype || deprec->deptype == deptype))
+				{
+					result = lappend_oid(result, deprec->objid);
+				}
+				break;
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 	}
 
@@ -940,9 +957,23 @@ get_constraint_index(Oid constraintId)
 			 * This is pure paranoia; there shouldn't be any other relkinds
 			 * dependent on a constraint.
 			 */
-			if (relkind != RELKIND_INDEX &&
-				relkind != RELKIND_PARTITIONED_INDEX)
-				continue;
+			switch ((RelKind) relkind)
+			{
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+					break;
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					continue;
+			}
 
 			indexId = deprec->objid;
 			break;
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 09946be788..336de8e97f 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -50,13 +50,27 @@ static void
 check_publication_add_relation(Relation targetrel)
 {
 	/* Must be a regular or partitioned table */
-	if (RelationGetForm(targetrel)->relkind != RELKIND_RELATION &&
-		RelationGetForm(targetrel)->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("\"%s\" is not a table",
-						RelationGetRelationName(targetrel)),
-				 errdetail("Only tables can be added to publications.")));
+	switch ((RelKind) RelationGetForm(targetrel)->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("\"%s\" is not a table",
+							RelationGetRelationName(targetrel)),
+					 errdetail("Only tables can be added to publications.")));
+	}
 
 	/* Can't be system table */
 	if (IsCatalogRelation(targetrel))
@@ -97,11 +111,26 @@ check_publication_add_relation(Relation targetrel)
 static bool
 is_publishable_class(Oid relid, Form_pg_class reltuple)
 {
-	return (reltuple->relkind == RELKIND_RELATION ||
-			reltuple->relkind == RELKIND_PARTITIONED_TABLE) &&
-		!IsCatalogRelationOid(relid) &&
-		reltuple->relpersistence == RELPERSISTENCE_PERMANENT &&
-		relid >= FirstNormalObjectId;
+	switch ((RelKind) reltuple->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			return (!IsCatalogRelationOid(relid) &&
+					reltuple->relpersistence == RELPERSISTENCE_PERMANENT &&
+					relid >= FirstNormalObjectId);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return false;
+	}
 }
 
 /*
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 79ffe317dd..bca5c5b1fa 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -658,10 +658,25 @@ GenerateTypeDependencies(HeapTuple typeTuple,
 	{
 		ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
 
-		if (relationKind != RELKIND_COMPOSITE_TYPE)
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
-		else
-			recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
+		switch ((RelKind) relationKind)
+		{
+			case RELKIND_COMPOSITE_TYPE:
+				recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+				break;
+		}
 	}
 
 	/*
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 3f7ab8d389..d878d07660 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -99,12 +99,27 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
 
 	rel = table_openrv(makeRangeVar(NULL, relName, -1), AccessExclusiveLock);
 
-	if (rel->rd_rel->relkind != RELKIND_RELATION &&
-		rel->rd_rel->relkind != RELKIND_MATVIEW)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table or materialized view",
-						relName)));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table or materialized view",
+							relName)));
+			break;
+	}
 
 	/* create_toast_table does all the work */
 	if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0,
@@ -394,8 +409,23 @@ needs_toast_table(Relation rel)
 	/*
 	 * No need to create a TOAST table for partitioned tables.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		return false;
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			return false;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * We cannot allow toasting a shared relation after initdb (because
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 924ef37c81..1a64bc22e9 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -196,54 +196,75 @@ analyze_rel(Oid relid, RangeVar *relation,
 	/*
 	 * Check that it's of an analyzable relkind, and set up appropriately.
 	 */
-	if (onerel->rd_rel->relkind == RELKIND_RELATION ||
-		onerel->rd_rel->relkind == RELKIND_MATVIEW)
+	switch ((RelKind) onerel->rd_rel->relkind)
 	{
-		/* Regular table, so we'll use the regular row acquisition function */
-		acquirefunc = acquire_sample_rows;
-		/* Also get regular table's size */
-		relpages = RelationGetNumberOfBlocks(onerel);
-	}
-	else if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-	{
-		/*
-		 * For a foreign table, call the FDW's hook function to see whether it
-		 * supports analysis.
-		 */
-		FdwRoutine *fdwroutine;
-		bool		ok = false;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+			{
+				/*
+				 * Regular table, so we'll use the regular row acquisition
+				 * function
+				 */
+				acquirefunc = acquire_sample_rows;
+				/* Also get regular table's size */
+				relpages = RelationGetNumberOfBlocks(onerel);
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			{
+				/*
+				 * For a foreign table, call the FDW's hook function to see
+				 * whether it supports analysis.
+				 */
+				FdwRoutine *fdwroutine;
+				bool		ok = false;
 
-		fdwroutine = GetFdwRoutineForRelation(onerel, false);
+				fdwroutine = GetFdwRoutineForRelation(onerel, false);
 
-		if (fdwroutine->AnalyzeForeignTable != NULL)
-			ok = fdwroutine->AnalyzeForeignTable(onerel,
-												 &acquirefunc,
-												 &relpages);
+				if (fdwroutine->AnalyzeForeignTable != NULL)
+					ok = fdwroutine->AnalyzeForeignTable(onerel,
+														 &acquirefunc,
+														 &relpages);
 
-		if (!ok)
-		{
-			ereport(WARNING,
-					(errmsg("skipping \"%s\" --- cannot analyze this foreign table",
-							RelationGetRelationName(onerel))));
-			relation_close(onerel, ShareUpdateExclusiveLock);
-			return;
-		}
-	}
-	else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-	{
-		/*
-		 * For partitioned tables, we want to do the recursive ANALYZE below.
-		 */
-	}
-	else
-	{
-		/* No need for a WARNING if we already complained during VACUUM */
-		if (!(params->options & VACOPT_VACUUM))
-			ereport(WARNING,
-					(errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
-							RelationGetRelationName(onerel))));
-		relation_close(onerel, ShareUpdateExclusiveLock);
-		return;
+				if (!ok)
+				{
+					ereport(WARNING,
+							(errmsg("skipping \"%s\" --- cannot analyze this foreign table",
+									RelationGetRelationName(onerel))));
+					relation_close(onerel, ShareUpdateExclusiveLock);
+					return;
+				}
+			}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				/*
+				 * For partitioned tables, we want to do the recursive ANALYZE
+				 * below.
+				 */
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			{
+				/*
+				 * No need for a WARNING if we already complained during
+				 * VACUUM
+				 */
+				if (!(params->options & VACOPT_VACUUM))
+					ereport(WARNING,
+							(errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
+									RelationGetRelationName(onerel))));
+				relation_close(onerel, ShareUpdateExclusiveLock);
+				return;
+			}
+			break;
 	}
 
 	/*
@@ -259,9 +280,25 @@ analyze_rel(Oid relid, RangeVar *relation,
 	 * Do the normal non-recursive ANALYZE.  We can skip this for partitioned
 	 * tables, which don't contain any rows.
 	 */
-	if (onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		do_analyze_rel(onerel, params, va_cols, acquirefunc,
-					   relpages, false, in_outer_xact, elevel);
+	switch ((RelKind) onerel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			do_analyze_rel(onerel, params, va_cols, acquirefunc,
+						   relpages, false, in_outer_xact, elevel);
+			break;
+	}
 
 	/*
 	 * If there are child tables, do recursive ANALYZE.
@@ -1283,49 +1320,67 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
 		}
 
 		/* Check table type (MATVIEW can't happen, but might as well allow) */
-		if (childrel->rd_rel->relkind == RELKIND_RELATION ||
-			childrel->rd_rel->relkind == RELKIND_MATVIEW)
-		{
-			/* Regular table, so use the regular row acquisition function */
-			acquirefunc = acquire_sample_rows;
-			relpages = RelationGetNumberOfBlocks(childrel);
-		}
-		else if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+		switch ((RelKind) childrel->rd_rel->relkind)
 		{
-			/*
-			 * For a foreign table, call the FDW's hook function to see
-			 * whether it supports analysis.
-			 */
-			FdwRoutine *fdwroutine;
-			bool		ok = false;
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+				{
+					/*
+					 * Regular table, so use the regular row acquisition
+					 * function
+					 */
+					acquirefunc = acquire_sample_rows;
+					relpages = RelationGetNumberOfBlocks(childrel);
+				}
+				break;
+			case RELKIND_FOREIGN_TABLE:
+				{
+					/*
+					 * For a foreign table, call the FDW's hook function to
+					 * see whether it supports analysis.
+					 */
+					FdwRoutine *fdwroutine;
+					bool		ok = false;
 
-			fdwroutine = GetFdwRoutineForRelation(childrel, false);
+					fdwroutine = GetFdwRoutineForRelation(childrel, false);
 
-			if (fdwroutine->AnalyzeForeignTable != NULL)
-				ok = fdwroutine->AnalyzeForeignTable(childrel,
-													 &acquirefunc,
-													 &relpages);
+					if (fdwroutine->AnalyzeForeignTable != NULL)
+						ok = fdwroutine->AnalyzeForeignTable(childrel,
+															 &acquirefunc,
+															 &relpages);
 
-			if (!ok)
-			{
-				/* ignore, but release the lock on it */
-				Assert(childrel != onerel);
-				table_close(childrel, AccessShareLock);
-				continue;
-			}
-		}
-		else
-		{
-			/*
-			 * ignore, but release the lock on it.  don't try to unlock the
-			 * passed-in relation
-			 */
-			Assert(childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
-			if (childrel != onerel)
-				table_close(childrel, AccessShareLock);
-			else
-				table_close(childrel, NoLock);
-			continue;
+					if (!ok)
+					{
+						/* ignore, but release the lock on it */
+						Assert(childrel != onerel);
+						table_close(childrel, AccessShareLock);
+						continue;
+					}
+				}
+				break;
+			case RELKIND_PARTITIONED_TABLE:
+				{
+					/*
+					 * ignore, but release the lock on it.  don't try to
+					 * unlock the passed-in relation
+					 */
+					if (childrel != onerel)
+						table_close(childrel, AccessShareLock);
+					else
+						table_close(childrel, NoLock);
+					continue;
+				}
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				Assert(false);
+				break;
 		}
 
 		/* OK, we'll process this child */
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 04d12a7ece..d1ac9a51e4 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -127,10 +127,26 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
 		/*
 		 * Reject clustering a partitioned table.
 		 */
-		if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot cluster a partitioned table")));
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				ereport(ERROR,
+						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 errmsg("cannot cluster a partitioned table")));
+				break;
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		if (stmt->indexname == NULL)
 		{
@@ -383,12 +399,28 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
 	 * multi-relation request -- for example, CLUSTER was run on the entire
 	 * database.
 	 */
-	if (OldHeap->rd_rel->relkind == RELKIND_MATVIEW &&
-		!RelationIsPopulated(OldHeap))
+	switch ((RelKind) OldHeap->rd_rel->relkind)
 	{
-		relation_close(OldHeap, AccessExclusiveLock);
-		pgstat_progress_end_command();
-		return;
+		case RELKIND_MATVIEW:
+			if (!RelationIsPopulated(OldHeap))
+			{
+				relation_close(OldHeap, AccessExclusiveLock);
+				pgstat_progress_end_command();
+				return;
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -484,10 +516,26 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
 	ListCell   *index;
 
 	/* Disallow applying to a partitioned table */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("cannot mark index clustered in partitioned table")));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("cannot mark index clustered in partitioned table")));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * If the index is already marked clustered, no need to do anything.
@@ -1103,12 +1151,26 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
 	 */
 
 	/* set rel1's frozen Xid and minimum MultiXid */
-	if (relform1->relkind != RELKIND_INDEX)
+	switch ((RelKind) relform1->relkind)
 	{
-		Assert(!TransactionIdIsValid(frozenXid) ||
-			   TransactionIdIsNormal(frozenXid));
-		relform1->relfrozenxid = frozenXid;
-		relform1->relminmxid = cutoffMulti;
+		case RELKIND_INDEX:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			Assert(!TransactionIdIsValid(frozenXid) ||
+				   TransactionIdIsNormal(frozenXid));
+			relform1->relfrozenxid = frozenXid;
+			relform1->relminmxid = cutoffMulti;
+			break;
 	}
 
 	/* swap size statistics too, since new rel has freshly-updated stats */
@@ -1267,27 +1329,43 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
 	 * valid index. The swap can actually be safely done only if the relations
 	 * have indexes.
 	 */
-	if (swap_toast_by_content &&
-		relform1->relkind == RELKIND_TOASTVALUE &&
-		relform2->relkind == RELKIND_TOASTVALUE)
+	switch ((RelKind) relform1->relkind)
 	{
-		Oid			toastIndex1,
-					toastIndex2;
-
-		/* Get valid index for each relation */
-		toastIndex1 = toast_get_valid_index(r1,
-											AccessExclusiveLock);
-		toastIndex2 = toast_get_valid_index(r2,
-											AccessExclusiveLock);
-
-		swap_relation_files(toastIndex1,
-							toastIndex2,
-							target_is_pg_class,
-							swap_toast_by_content,
-							is_internal,
-							InvalidTransactionId,
-							InvalidMultiXactId,
-							mapped_tables);
+		case RELKIND_TOASTVALUE:
+			if (swap_toast_by_content &&
+				relform2->relkind == RELKIND_TOASTVALUE)
+			{
+				Oid			toastIndex1,
+							toastIndex2;
+
+				/* Get valid index for each relation */
+				toastIndex1 = toast_get_valid_index(r1,
+													AccessExclusiveLock);
+				toastIndex2 = toast_get_valid_index(r2,
+													AccessExclusiveLock);
+
+				swap_relation_files(toastIndex1,
+									toastIndex2,
+									target_is_pg_class,
+									swap_toast_by_content,
+									is_internal,
+									InvalidTransactionId,
+									InvalidMultiXactId,
+									mapped_tables);
+			}
+			break;
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* Clean up. */
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 0ff9ca9f2c..400b14cc54 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -90,16 +90,27 @@ CommentObject(CommentStmt *stmt)
 			 * versions, so dumping per-column comments could create reload
 			 * failures.
 			 */
-			if (relation->rd_rel->relkind != RELKIND_RELATION &&
-				relation->rd_rel->relkind != RELKIND_VIEW &&
-				relation->rd_rel->relkind != RELKIND_MATVIEW &&
-				relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
-				relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-				relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_RELATION:
+				case RELKIND_VIEW:
+				case RELKIND_MATVIEW:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_PARTITIONED_TABLE:
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
+									RelationGetRelationName(relation))));
+					break;
+			}
 			break;
 		default:
 			break;
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 3e199bdfd0..01a5261506 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -1831,42 +1831,58 @@ BeginCopyTo(ParseState *pstate,
 	bool		pipe = (filename == NULL);
 	MemoryContext oldcontext;
 
-	if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
+	if (rel != NULL)
 	{
-		if (rel->rd_rel->relkind == RELKIND_VIEW)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy from view \"%s\"",
-							RelationGetRelationName(rel)),
-					 errhint("Try the COPY (SELECT ...) TO variant.")));
-		else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy from materialized view \"%s\"",
-							RelationGetRelationName(rel)),
-					 errhint("Try the COPY (SELECT ...) TO variant.")));
-		else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy from foreign table \"%s\"",
-							RelationGetRelationName(rel)),
-					 errhint("Try the COPY (SELECT ...) TO variant.")));
-		else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy from sequence \"%s\"",
-							RelationGetRelationName(rel))));
-		else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy from partitioned table \"%s\"",
-							RelationGetRelationName(rel)),
-					 errhint("Try the COPY (SELECT ...) TO variant.")));
-		else
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy from non-table relation \"%s\"",
-							RelationGetRelationName(rel))));
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+			case RELKIND_RELATION:
+				break;
+			case RELKIND_SEQUENCE:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy from sequence \"%s\"",
+								RelationGetRelationName(rel))));
+				break;
+			case RELKIND_FOREIGN_TABLE:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy from foreign table \"%s\"",
+								RelationGetRelationName(rel)),
+						 errhint("Try the COPY (SELECT ...) TO variant.")));
+				break;
+			case RELKIND_MATVIEW:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy from materialized view \"%s\"",
+								RelationGetRelationName(rel)),
+						 errhint("Try the COPY (SELECT ...) TO variant.")));
+				break;
+			case RELKIND_PARTITIONED_TABLE:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy from partitioned table \"%s\"",
+								RelationGetRelationName(rel)),
+						 errhint("Try the COPY (SELECT ...) TO variant.")));
+				break;
+			case RELKIND_VIEW:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy from view \"%s\"",
+								RelationGetRelationName(rel)),
+						 errhint("Try the COPY (SELECT ...) TO variant.")));
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy from non-table relation \"%s\"",
+								RelationGetRelationName(rel))));
+				break;
+		}
 	}
 
 	cstate = BeginCopy(pstate, false, rel, query, queryRelId, attnamelist,
@@ -2390,8 +2406,24 @@ CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri,
 	 * Buffers for partitioned tables will just be setup when we need to send
 	 * tuples their way for the first time.
 	 */
-	if (rri->ri_RelationDesc->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		CopyMultiInsertInfoSetupBuffer(miinfo, rri);
+	switch ((RelKind) rri->ri_RelationDesc->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			CopyMultiInsertInfoSetupBuffer(miinfo, rri);
+			break;
+	}
 }
 
 /*
@@ -2675,33 +2707,46 @@ CopyFrom(CopyState cstate)
 	 * an INSTEAD OF INSERT row trigger.  (Currently, such triggers are only
 	 * allowed on views, so we only hint about them in the view case.)
 	 */
-	if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
-		cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-		cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
-		!(cstate->rel->trigdesc &&
+	if (!(cstate->rel->trigdesc &&
 		  cstate->rel->trigdesc->trig_insert_instead_row))
 	{
-		if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy to view \"%s\"",
-							RelationGetRelationName(cstate->rel)),
-					 errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
-		else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy to materialized view \"%s\"",
-							RelationGetRelationName(cstate->rel))));
-		else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy to sequence \"%s\"",
-							RelationGetRelationName(cstate->rel))));
-		else
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot copy to non-table relation \"%s\"",
-							RelationGetRelationName(cstate->rel))));
+		switch ((RelKind) cstate->rel->rd_rel->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_VIEW:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy to view \"%s\"",
+								RelationGetRelationName(cstate->rel)),
+						 errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
+				break;
+			case RELKIND_MATVIEW:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy to materialized view \"%s\"",
+								RelationGetRelationName(cstate->rel))));
+				break;
+			case RELKIND_SEQUENCE:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy to sequence \"%s\"",
+								RelationGetRelationName(cstate->rel))));
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot copy to non-table relation \"%s\"",
+								RelationGetRelationName(cstate->rel))));
+				break;
+		}
 	}
 
 	/*
@@ -2736,11 +2781,25 @@ CopyFrom(CopyState cstate)
 		 * tuples to a small number of partitions.  It seems better just to
 		 * raise an ERROR for partitioned tables.
 		 */
-		if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+		switch ((RelKind) cstate->rel->rd_rel->relkind)
 		{
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot perform COPY FREEZE on a partitioned table")));
+			case RELKIND_PARTITIONED_TABLE:
+				ereport(ERROR,
+						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 errmsg("cannot perform COPY FREEZE on a partitioned table")));
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/*
@@ -2825,8 +2884,24 @@ CopyFrom(CopyState cstate)
 	 * If the named relation is a partitioned table, initialize state for
 	 * CopyFrom tuple routing.
 	 */
-	if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		proute = ExecSetupPartitionTupleRouting(estate, NULL, cstate->rel);
+	switch ((RelKind) cstate->rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			proute = ExecSetupPartitionTupleRouting(estate, NULL, cstate->rel);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	if (cstate->whereClause)
 		cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 472e69fdaf..a8375d3b5d 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3280,8 +3280,8 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 		case OBJECT_SUBSCRIPTION:
 		case OBJECT_TABLESPACE:
 			ereport(ERROR,
-				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				 errmsg("cannot add an object of this type to an extension")));
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+					 errmsg("cannot add an object of this type to an extension")));
 			break;
 		default:
 			/* OK */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 2baca12c5f..194e1836cb 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -615,7 +615,7 @@ DefineIndex(Oid relationId,
 	namespaceId = RelationGetNamespace(rel);
 
 	/* Ensure that it makes sense to index this kind of relation */
-	switch (rel->rd_rel->relkind)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
@@ -633,6 +633,13 @@ DefineIndex(Oid relationId,
 					 errmsg("cannot create index on foreign table \"%s\"",
 							RelationGetRelationName(rel))));
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -1190,18 +1197,33 @@ DefineIndex(Oid relationId,
 				 * those if a regular index, or fail if trying to create a
 				 * constraint index.
 				 */
-				if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+				switch ((RelKind) childrel->rd_rel->relkind)
 				{
-					if (stmt->unique || stmt->primary)
-						ereport(ERROR,
-								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-								 errmsg("cannot create unique index on partitioned table \"%s\"",
-										RelationGetRelationName(rel)),
-								 errdetail("Table \"%s\" contains partitions that are foreign tables.",
-										   RelationGetRelationName(rel))));
-
-					table_close(childrel, lockmode);
-					continue;
+					case RELKIND_FOREIGN_TABLE:
+						{
+							if (stmt->unique || stmt->primary)
+								ereport(ERROR,
+										(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+										 errmsg("cannot create unique index on partitioned table \"%s\"",
+												RelationGetRelationName(rel)),
+										 errdetail("Table \"%s\" contains partitions that are foreign tables.",
+												   RelationGetRelationName(rel))));
+
+							table_close(childrel, lockmode);
+							continue;
+						}
+						break;
+					case RELKIND_SEQUENCE:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_INDEX:
+					case RELKIND_MATVIEW:
+					case RELKIND_PARTITIONED_TABLE:
+					case RELKIND_RELATION:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_VIEW:
+					case RELKIND_NULL:
+					default:
+						break;
 				}
 
 				childidxs = RelationGetIndexList(childrel);
@@ -2451,10 +2473,23 @@ ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
 	 */
 	irel = index_open(indOid, NoLock);
 
-	if (irel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+	switch ((RelKind) irel->rd_rel->relkind)
 	{
-		ReindexPartitionedIndex(irel);
-		return;
+		case RELKIND_PARTITIONED_INDEX:
+			ReindexPartitionedIndex(irel);
+			return;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	persistence = irel->rd_rel->relpersistence;
@@ -2510,11 +2545,25 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
 	relkind = get_rel_relkind(relId);
 	if (!relkind)
 		return;
-	if (relkind != RELKIND_INDEX &&
-		relkind != RELKIND_PARTITIONED_INDEX)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not an index", relation->relname)));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not an index", relation->relname)));
+	}
 
 	/* Check permissions */
 	if (!pg_class_ownercheck(relId, GetUserId()))
@@ -2694,9 +2743,23 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
 		 * partitioned tables, and expand that afterwards into relids,
 		 * ignoring any duplicates.
 		 */
-		if (classtuple->relkind != RELKIND_RELATION &&
-			classtuple->relkind != RELKIND_MATVIEW)
-			continue;
+		switch ((RelKind) classtuple->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				continue;
+		}
 
 		/* Skip temp tables of other backends; we can't reindex them at all */
 		if (classtuple->relpersistence == RELPERSISTENCE_TEMP &&
@@ -2867,7 +2930,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 	 * Extract the list of indexes that are going to be rebuilt based on the
 	 * relation Oid given by caller.
 	 */
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
@@ -3017,6 +3080,12 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 					 errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
 							get_rel_name(relationOid))));
 			return false;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* Return error if type of relation is not supported */
 			ereport(ERROR,
@@ -3443,30 +3512,43 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 	/* Log what we did */
 	if (options & REINDEXOPT_VERBOSE)
 	{
-		if (relkind == RELKIND_INDEX)
-			ereport(INFO,
-					(errmsg("index \"%s.%s\" was reindexed",
-							relationNamespace, relationName),
-					 errdetail("%s.",
-							   pg_rusage_show(&ru0))));
-		else
+		switch ((RelKind) relkind)
 		{
-			foreach(lc, newIndexIds)
-			{
-				Oid			indOid = lfirst_oid(lc);
-
+			case RELKIND_INDEX:
 				ereport(INFO,
 						(errmsg("index \"%s.%s\" was reindexed",
-								get_namespace_name(get_rel_namespace(indOid)),
-								get_rel_name(indOid))));
-				/* Don't show rusage here, since it's not per index. */
-			}
+								relationNamespace, relationName),
+						 errdetail("%s.",
+								   pg_rusage_show(&ru0))));
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				foreach(lc, newIndexIds)
+				{
+					Oid			indOid = lfirst_oid(lc);
+
+					ereport(INFO,
+							(errmsg("index \"%s.%s\" was reindexed",
+									get_namespace_name(get_rel_namespace(indOid)),
+									get_rel_name(indOid))));
+					/* Don't show rusage here, since it's not per index. */
+				}
 
-			ereport(INFO,
-					(errmsg("table \"%s.%s\" was reindexed",
-							relationNamespace, relationName),
-					 errdetail("%s.",
-							   pg_rusage_show(&ru0))));
+				ereport(INFO,
+						(errmsg("table \"%s.%s\" was reindexed",
+								relationNamespace, relationName),
+						 errdetail("%s.",
+								   pg_rusage_show(&ru0))));
+				break;
 		}
 	}
 
@@ -3508,8 +3590,24 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
 	bool		fix_dependencies;
 
 	/* Make sure this is an index */
-	Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
-		   partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
+	switch ((RelKind) partitionIdx->rd_rel->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			break;				/* ok */
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			Assert(false);
+			break;
+	}
 
 	/*
 	 * Scan pg_inherits for rows linking our index to some parent.
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index d8cafc42bb..deb885adf8 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -56,10 +56,26 @@ LockTableCommand(LockStmt *lockstmt)
 										  RangeVarCallbackForLockTable,
 										  (void *) &lockstmt->mode);
 
-		if (get_rel_relkind(reloid) == RELKIND_VIEW)
-			LockViewRecurse(reloid, lockstmt->mode, lockstmt->nowait, NIL);
-		else if (recurse)
-			LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait);
+		switch ((RelKind) get_rel_relkind(reloid))
+		{
+			case RELKIND_VIEW:
+				LockViewRecurse(reloid, lockstmt->mode, lockstmt->nowait, NIL);
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				if (recurse)
+					LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait);
+				break;
+		}
 	}
 }
 
@@ -84,12 +100,27 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
 								 * check */
 
 	/* Currently, we only allow plain tables or views to be locked */
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE &&
-		relkind != RELKIND_VIEW)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table or view",
-						rv->relname)));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table or view",
+							rv->relname)));
+			break;
+	}
 
 	/*
 	 * Make note if a temporary relation has been accessed in this
@@ -201,10 +232,27 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 				 strcmp(rte->eref->aliasname, "new") == 0))
 				continue;
 
-			/* Currently, we only allow plain tables or views to be locked. */
-			if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE &&
-				relkind != RELKIND_VIEW)
-				continue;
+			switch ((RelKind) relkind)
+			{
+					/*
+					 * Currently, we only allow plain tables or views to be
+					 * locked.
+					 */
+				case RELKIND_RELATION:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_VIEW:
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					continue;
+			}
 
 			/* Check infinite recursion in the view definition. */
 			if (list_member_oid(context->ancestor_views, relid))
@@ -227,10 +275,26 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 						 errmsg("could not obtain lock on relation \"%s\"",
 								relname)));
 
-			if (relkind == RELKIND_VIEW)
-				LockViewRecurse(relid, context->lockmode, context->nowait, context->ancestor_views);
-			else if (rte->inh)
-				LockTableRecurse(relid, context->lockmode, context->nowait);
+			switch ((RelKind) relkind)
+			{
+				case RELKIND_VIEW:
+					LockViewRecurse(relid, context->lockmode, context->nowait, context->ancestor_views);
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					if (rte->inh)
+						LockTableRecurse(relid, context->lockmode, context->nowait);
+					break;
+			}
 		}
 
 		return query_tree_walker(query,
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 4b4e469493..f96459bc93 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -89,10 +89,26 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
 						rv->relname)));
 
 	/* Relation type MUST be a table. */
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table", rv->relname)));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table", rv->relname)));
+			break;
+	}
 
 	ReleaseSysCache(tuple);
 }
@@ -388,12 +404,27 @@ RemovePolicyById(Oid policy_id)
 	relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
 
 	rel = table_open(relid, AccessExclusiveLock);
-	if (rel->rd_rel->relkind != RELKIND_RELATION &&
-		rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 
 	if (!allowSystemTableMods && IsSystemRelation(rel))
 		ereport(ERROR,
@@ -478,12 +509,27 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
 
 	rel = relation_open(relid, AccessExclusiveLock);
 
-	if (rel->rd_rel->relkind != RELKIND_RELATION &&
-		rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 
 	if (!allowSystemTableMods && IsSystemRelation(rel))
 		ereport(ERROR,
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index eabbc7473b..b340fd9b9c 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -548,33 +548,49 @@ OpenTableList(List *tables)
 		 * children other than its partitions, which need not be explicitly
 		 * added to the publication.
 		 */
-		if (recurse && rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+		switch ((RelKind) rel->rd_rel->relkind)
 		{
-			List	   *children;
-			ListCell   *child;
-
-			children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
-										   NULL);
-
-			foreach(child, children)
-			{
-				Oid			childrelid = lfirst_oid(child);
-
-				/* Allow query cancel in case this takes a long time */
-				CHECK_FOR_INTERRUPTS();
-
-				/*
-				 * Skip duplicates if user specified both parent and child
-				 * tables.
-				 */
-				if (list_member_oid(relids, childrelid))
-					continue;
-
-				/* find_all_inheritors already got lock */
-				rel = table_open(childrelid, NoLock);
-				rels = lappend(rels, rel);
-				relids = lappend_oid(relids, childrelid);
-			}
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				if (recurse)
+				{
+					List	   *children;
+					ListCell   *child;
+
+					children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
+												   NULL);
+
+					foreach(child, children)
+					{
+						Oid			childrelid = lfirst_oid(child);
+
+						/* Allow query cancel in case this takes a long time */
+						CHECK_FOR_INTERRUPTS();
+
+						/*
+						 * Skip duplicates if user specified both parent and
+						 * child tables.
+						 */
+						if (list_member_oid(relids, childrelid))
+							continue;
+
+						/* find_all_inheritors already got lock */
+						rel = table_open(childrelid, NoLock);
+						rels = lappend(rels, rel);
+						relids = lappend_oid(relids, childrelid);
+					}
+				}
 		}
 	}
 
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index ee036e9087..77bd351b96 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -180,16 +180,27 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
 			 * materialized views, composite types, and foreign tables (which
 			 * are the only relkinds for which pg_dump will dump labels).
 			 */
-			if (relation->rd_rel->relkind != RELKIND_RELATION &&
-				relation->rd_rel->relkind != RELKIND_VIEW &&
-				relation->rd_rel->relkind != RELKIND_MATVIEW &&
-				relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
-				relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-				relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
-								RelationGetRelationName(relation))));
+			switch ((RelKind) relation->rd_rel->relkind)
+			{
+				case RELKIND_RELATION:
+				case RELKIND_VIEW:
+				case RELKIND_MATVIEW:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_PARTITIONED_TABLE:
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
+									RelationGetRelationName(relation))));
+					break;
+			}
 			break;
 		default:
 			break;
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 6aab73bfd4..6652bcff7f 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1675,14 +1675,27 @@ process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
 		tablerel = relation_openrv(rel, AccessShareLock);
 
 		/* Must be a regular or foreign table */
-		if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
-			  tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
-			  tablerel->rd_rel->relkind == RELKIND_VIEW ||
-			  tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("referenced relation \"%s\" is not a table or foreign table",
-							RelationGetRelationName(tablerel))));
+		switch ((RelKind) tablerel->rd_rel->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("referenced relation \"%s\" is not a table or foreign table",
+								RelationGetRelationName(tablerel))));
+				break;
+		}
 
 		/* We insist on same owner and schema */
 		if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index 974828545c..d0976ae826 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -122,14 +122,27 @@ CreateStatistics(CreateStatsStmt *stmt)
 		rel = relation_openrv((RangeVar *) rln, ShareUpdateExclusiveLock);
 
 		/* Restrict to allowed relation types */
-		if (rel->rd_rel->relkind != RELKIND_RELATION &&
-			rel->rd_rel->relkind != RELKIND_MATVIEW &&
-			rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-			rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("relation \"%s\" is not a table, foreign table, or materialized view",
-							RelationGetRelationName(rel))));
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("relation \"%s\" is not a table, foreign table, or materialized view",
+								RelationGetRelationName(rel))));
+				break;
+		}
 
 		/* You must own the relation to create stats on it */
 		if (!pg_class_ownercheck(RelationGetRelid(rel), stxowner))
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 1105c5b8ec..0dd3b07c77 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -619,8 +619,24 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 
 	if (stmt->partspec != NULL)
 	{
-		if (relkind != RELKIND_RELATION)
-			elog(ERROR, "unexpected relkind: %d", (int) relkind);
+		switch ((RelKind) relkind)
+		{
+			case RELKIND_RELATION:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				elog(ERROR, "unexpected relkind: %d", (int) relkind);
+				break;
+		}
 
 		relkind = RELKIND_PARTITIONED_TABLE;
 		partitioned = true;
@@ -746,7 +762,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
 									 true, false);
 
-	switch (relkind)
+	switch ((RelKind) relkind)
 	{
 		case RELKIND_VIEW:
 			(void) view_reloptions(reloptions, true);
@@ -754,6 +770,15 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 		case RELKIND_PARTITIONED_TABLE:
 			(void) partitioned_table_reloptions(reloptions, true);
 			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			(void) heap_reloptions(relkind, reloptions, true);
 	}
@@ -866,10 +891,25 @@ 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)
-		accessMethod = default_table_access_method;
+	else
+		switch ((RelKind) relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_MATVIEW:
+				accessMethod = default_table_access_method;
+				break;
+			case RELKIND_VIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_INDEX:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 	/* look up the access method, verify it is for a table */
 	if (accessMethod != NULL)
@@ -956,11 +996,26 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 		 * We are going to try to validate the partition bound specification
 		 * against the partition key of parentRel, so it better have one.
 		 */
-		if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-					 errmsg("\"%s\" is not partitioned",
-							RelationGetRelationName(parent))));
+		switch ((RelKind) parent->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_INDEX:
+			case RELKIND_NULL:
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+						 errmsg("\"%s\" is not partitioned",
+								RelationGetRelationName(parent))));
+		}
 
 		/*
 		 * The partition constraint of the default partition depends on the
@@ -1104,20 +1159,34 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 			IndexStmt  *idxstmt;
 			Oid			constraintOid;
 
-			if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+			switch ((RelKind) rel->rd_rel->relkind)
 			{
-				if (idxRel->rd_index->indisunique)
-					ereport(ERROR,
-							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-							 errmsg("cannot create foreign partition of partitioned table \"%s\"",
-									RelationGetRelationName(parent)),
-							 errdetail("Table \"%s\" contains indexes that are unique.",
-									   RelationGetRelationName(parent))));
-				else
-				{
-					index_close(idxRel, AccessShareLock);
-					continue;
-				}
+				case RELKIND_FOREIGN_TABLE:
+					if (idxRel->rd_index->indisunique)
+						ereport(ERROR,
+								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+								 errmsg("cannot create foreign partition of partitioned table \"%s\"",
+										RelationGetRelationName(parent)),
+								 errdetail("Table \"%s\" contains indexes that are unique.",
+										   RelationGetRelationName(parent))));
+					else
+					{
+						index_close(idxRel, AccessShareLock);
+						continue;
+					}
+					break;
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_MATVIEW:
+				case RELKIND_VIEW:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_SEQUENCE:
+				case RELKIND_INDEX:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 
 			attmap = build_attrmap_by_name(RelationGetDescr(rel),
@@ -1448,12 +1517,27 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
 	 * the relation is RELKIND_PARTITIONED_TABLE.  An equivalent problem
 	 * exists with indexes.
 	 */
-	if (classform->relkind == RELKIND_PARTITIONED_TABLE)
-		expected_relkind = RELKIND_RELATION;
-	else if (classform->relkind == RELKIND_PARTITIONED_INDEX)
-		expected_relkind = RELKIND_INDEX;
-	else
-		expected_relkind = classform->relkind;
+	switch ((RelKind) classform->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			expected_relkind = RELKIND_RELATION;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+			expected_relkind = RELKIND_INDEX;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_INDEX:
+		case RELKIND_NULL:
+		default:
+			expected_relkind = classform->relkind;
+			break;
+	}
 
 	if (relkind != expected_relkind)
 		DropErrorMsgWrongType(rel->relname, classform->relkind, relkind);
@@ -1470,26 +1554,43 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
 	 * only concerns indexes of toast relations that became invalid during a
 	 * REINDEX CONCURRENTLY process.
 	 */
-	if (IsSystemClass(relOid, classform) && relkind == RELKIND_INDEX)
+	switch ((RelKind) relkind)
 	{
-		HeapTuple	locTuple;
-		Form_pg_index indexform;
-		bool		indisvalid;
+		case RELKIND_INDEX:
+			if (IsSystemClass(relOid, classform))
+			{
+				HeapTuple	locTuple;
+				Form_pg_index indexform;
+				bool		indisvalid;
 
-		locTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relOid));
-		if (!HeapTupleIsValid(locTuple))
-		{
-			ReleaseSysCache(tuple);
-			return;
-		}
+				locTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relOid));
+				if (!HeapTupleIsValid(locTuple))
+				{
+					ReleaseSysCache(tuple);
+					return;
+				}
 
-		indexform = (Form_pg_index) GETSTRUCT(locTuple);
-		indisvalid = indexform->indisvalid;
-		ReleaseSysCache(locTuple);
+				indexform = (Form_pg_index) GETSTRUCT(locTuple);
+				indisvalid = indexform->indisvalid;
+				ReleaseSysCache(locTuple);
 
-		/* Mark object as being an invalid index of system catalogs */
-		if (!indisvalid)
-			invalid_system_index = true;
+				/* Mark object as being an invalid index of system catalogs */
+				if (!indisvalid)
+					invalid_system_index = true;
+			}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* In the case of an invalid index, it is fine to bypass this check */
@@ -1508,12 +1609,28 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
 	 * we do it the other way around.  No error if we don't find a pg_index
 	 * entry, though --- the relation may have been dropped.
 	 */
-	if ((relkind == RELKIND_INDEX || relkind == RELKIND_PARTITIONED_INDEX) &&
-		relOid != oldRelOid)
+	switch ((RelKind) relkind)
 	{
-		state->heapOid = IndexGetRelation(relOid, true);
-		if (OidIsValid(state->heapOid))
-			LockRelationOid(state->heapOid, heap_lockmode);
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			if (relOid != oldRelOid)
+			{
+				state->heapOid = IndexGetRelation(relOid, true);
+				if (OidIsValid(state->heapOid))
+					LockRelationOid(state->heapOid, heap_lockmode);
+			}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -1635,11 +1752,28 @@ ExecuteTruncate(TruncateStmt *stmt)
 					relids_logged = lappend_oid(relids_logged, childrelid);
 			}
 		}
-		else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot truncate only a partitioned table"),
-					 errhint("Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.")));
+		else
+			switch ((RelKind) rel->rd_rel->relkind)
+			{
+				case RELKIND_PARTITIONED_TABLE:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("cannot truncate only a partitioned table"),
+							 errhint("Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.")));
+					break;
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_MATVIEW:
+				case RELKIND_VIEW:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_SEQUENCE:
+				case RELKIND_NULL:
+				default:
+					break;
+			}
 	}
 
 	ExecuteTruncateGuts(rels, relids, relids_logged,
@@ -1815,9 +1949,24 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
 	{
 		Relation	rel = (Relation) lfirst(cell);
 
-		/* Skip partitioned tables as there is nothing to do */
-		if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			continue;
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+				/* Skip partitioned tables as there is nothing to do */
+			case RELKIND_PARTITIONED_TABLE:
+				continue;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_SEQUENCE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		/*
 		 * Normally, we need a transaction-safe truncation here.  However, if
@@ -1969,11 +2118,25 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple)
 	 * the latter are only being included here for the following checks; no
 	 * physical truncation will occur in their case.)
 	 */
-	if (reltuple->relkind != RELKIND_RELATION &&
-		reltuple->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table", relname)));
+	switch ((RelKind) reltuple->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table", relname)));
+	}
 
 	if (!allowSystemTableMods && IsSystemClass(relid, reltuple))
 		ereport(ERROR,
@@ -2235,26 +2398,39 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
 		 * We do not allow partitioned tables and partitions to participate in
 		 * regular inheritance.
 		 */
-		if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
-			!is_partition)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot inherit from partitioned table \"%s\"",
-							RelationGetRelationName(relation))));
+		switch ((RelKind) relation->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				if (!is_partition)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("cannot inherit from partitioned table \"%s\"",
+									RelationGetRelationName(relation))));
+				break;
+			case RELKIND_RELATION:
+			case RELKIND_FOREIGN_TABLE:
+				break;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_SEQUENCE:
+			case RELKIND_NULL:
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("inherited relation \"%s\" is not a table or foreign table",
+								RelationGetRelationName(relation))));
+		}
+
 		if (relation->rd_rel->relispartition && !is_partition)
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 					 errmsg("cannot inherit from partition \"%s\"",
 							RelationGetRelationName(relation))));
 
-		if (relation->rd_rel->relkind != RELKIND_RELATION &&
-			relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-			relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("inherited relation \"%s\" is not a table or foreign table",
-							RelationGetRelationName(relation))));
-
 		/*
 		 * If the parent is permanent, so must be all of its partitions.  Note
 		 * that inheritance allows that case.
@@ -2996,18 +3172,26 @@ renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
 	 * change names that are hardcoded into the system, hence the following
 	 * restriction.
 	 */
-	if (relkind != RELKIND_RELATION &&
-		relkind != RELKIND_VIEW &&
-		relkind != RELKIND_MATVIEW &&
-		relkind != RELKIND_COMPOSITE_TYPE &&
-		relkind != RELKIND_INDEX &&
-		relkind != RELKIND_PARTITIONED_INDEX &&
-		relkind != RELKIND_FOREIGN_TABLE &&
-		relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, view, materialized view, composite type, index, or foreign table",
-						NameStr(classform->relname))));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_TOASTVALUE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table, view, materialized view, composite type, index, or foreign table",
+							NameStr(classform->relname))));
+	}
 
 	/*
 	 * permissions checking.  only the owner of a class can change its schema.
@@ -3105,17 +3289,33 @@ renameatt_internal(Oid myrelid,
 	}
 
 	/* rename attributes in typed tables of composite type */
-	if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+	switch ((RelKind) targetrelation->rd_rel->relkind)
 	{
-		List	   *child_oids;
-		ListCell   *lo;
+		case RELKIND_COMPOSITE_TYPE:
+			{
+				List	   *child_oids;
+				ListCell   *lo;
 
-		child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
-												   RelationGetRelationName(targetrelation),
-												   behavior);
+				child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
+														   RelationGetRelationName(targetrelation),
+														   behavior);
 
-		foreach(lo, child_oids)
-			renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
+				foreach(lo, child_oids)
+					renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
+			}
+			break;
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	attrelation = table_open(AttributeRelationId, RowExclusiveLock);
@@ -3489,13 +3689,28 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo
 	/*
 	 * Also rename the associated constraint, if any.
 	 */
-	if (targetrelation->rd_rel->relkind == RELKIND_INDEX ||
-		targetrelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+	switch ((RelKind) targetrelation->rd_rel->relkind)
 	{
-		Oid			constraintId = get_index_constraint(myrelid);
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			{
+				Oid			constraintId = get_index_constraint(myrelid);
 
-		if (OidIsValid(constraintId))
-			RenameConstraintById(constraintId, newrelname);
+				if (OidIsValid(constraintId))
+					RenameConstraintById(constraintId, newrelname);
+			}
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -3542,14 +3757,29 @@ CheckTableNotInUse(Relation rel, const char *stmt)
 				 errmsg("cannot %s \"%s\" because it is being used by active queries in this session",
 						stmt, RelationGetRelationName(rel))));
 
-	if (rel->rd_rel->relkind != RELKIND_INDEX &&
-		rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX &&
-		AfterTriggerPendingOnRel(RelationGetRelid(rel)))
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_IN_USE),
-		/* translator: first %s is a SQL command, eg ALTER TABLE */
-				 errmsg("cannot %s \"%s\" because it has pending trigger events",
-						stmt, RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			if (AfterTriggerPendingOnRel(RelationGetRelid(rel)))
+				ereport(ERROR,
+						(errcode(ERRCODE_OBJECT_IN_USE),
+				/* translator: first %s is a SQL command, eg ALTER TABLE */
+						 errmsg("cannot %s \"%s\" because it has pending trigger events",
+								stmt, RelationGetRelationName(rel))));
+			break;
+	}
 }
 
 /*
@@ -4364,11 +4594,27 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 		 * not modify anything about it that will change its toasting
 		 * requirement, so no need to check.
 		 */
-		if (((tab->relkind == RELKIND_RELATION ||
-			  tab->relkind == RELKIND_PARTITIONED_TABLE) &&
-			 tab->partition_constraint == NULL) ||
-			tab->relkind == RELKIND_MATVIEW)
-			AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
+		switch ((RelKind) tab->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_TABLE:
+				if (tab->partition_constraint != NULL)
+					break;
+				/* fallthrough */
+			case RELKIND_MATVIEW:
+				AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
+				break;
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_VIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_SEQUENCE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 	}
 }
 
@@ -4546,15 +4792,29 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
 			break;
 		case AT_SetTableSpace:	/* SET TABLESPACE */
 
-			/*
-			 * Only do this for partitioned tables and indexes, for which this
-			 * is just a catalog change.  Other relation types which have
-			 * storage are handled by Phase 3.
-			 */
-			if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
-				rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-				ATExecSetTableSpaceNoStorage(rel, tab->newTableSpace);
-
+			switch ((RelKind) rel->rd_rel->relkind)
+			{
+					/*
+					 * Only do this for partitioned tables and indexes, for
+					 * which this is just a catalog change.  Other relation
+					 * types which have storage are handled by Phase 3.
+					 */
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_PARTITIONED_INDEX:
+					ATExecSetTableSpaceNoStorage(rel, tab->newTableSpace);
+					break;
+				case RELKIND_RELATION:
+				case RELKIND_MATVIEW:
+				case RELKIND_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_VIEW:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_SEQUENCE:
+				case RELKIND_NULL:
+				default:
+					break;
+			}
 			break;
 		case AT_SetRelOptions:	/* SET (...) */
 		case AT_ResetRelOptions:	/* RESET (...) */
@@ -4645,11 +4905,26 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
 			cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode,
 									  cur_pass, context);
 			Assert(cmd != NULL);
-			if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-				ATExecAttachPartition(wqueue, rel, (PartitionCmd *) cmd->def);
-			else
-				ATExecAttachPartitionIdx(wqueue, rel,
-										 ((PartitionCmd *) cmd->def)->name);
+			switch ((RelKind) rel->rd_rel->relkind)
+			{
+				case RELKIND_PARTITIONED_TABLE:
+					ATExecAttachPartition(wqueue, rel, (PartitionCmd *) cmd->def);
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_RELATION:
+				case RELKIND_MATVIEW:
+				case RELKIND_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_VIEW:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_SEQUENCE:
+				case RELKIND_NULL:
+				default:
+					ATExecAttachPartitionIdx(wqueue, rel,
+											 ((PartitionCmd *) cmd->def)->name);
+					break;
+			}
 			break;
 		case AT_DetachPartition:
 			cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode,
@@ -5477,7 +5752,7 @@ ATSimplePermissions(Relation rel, int allowed_targets)
 {
 	int			actual_target;
 
-	switch (rel->rd_rel->relkind)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -5501,6 +5776,9 @@ ATSimplePermissions(Relation rel, int allowed_targets)
 		case RELKIND_FOREIGN_TABLE:
 			actual_target = ATT_FOREIGN_TABLE;
 			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
 		default:
 			actual_target = 0;
 			break;
@@ -5600,35 +5878,49 @@ ATSimpleRecursion(List **wqueue, Relation rel,
 	 * and partitioned tables have children, so no need to search for other
 	 * relkinds.
 	 */
-	if (recurse &&
-		(rel->rd_rel->relkind == RELKIND_RELATION ||
-		 rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
-		 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		Oid			relid = RelationGetRelid(rel);
-		ListCell   *child;
-		List	   *children;
-
-		children = find_all_inheritors(relid, lockmode, NULL);
+		case RELKIND_RELATION:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			if (recurse)
+			{
+				Oid			relid = RelationGetRelid(rel);
+				ListCell   *child;
+				List	   *children;
 
-		/*
-		 * find_all_inheritors does the recursive search of the inheritance
-		 * hierarchy, so all we have to do is process all of the relids in the
-		 * list that it returns.
-		 */
-		foreach(child, children)
-		{
-			Oid			childrelid = lfirst_oid(child);
-			Relation	childrel;
+				children = find_all_inheritors(relid, lockmode, NULL);
 
-			if (childrelid == relid)
-				continue;
-			/* find_all_inheritors already got lock */
-			childrel = relation_open(childrelid, NoLock);
-			CheckTableNotInUse(childrel, "ALTER TABLE");
-			ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
-			relation_close(childrel, NoLock);
-		}
+				/*
+				 * find_all_inheritors does the recursive search of the
+				 * inheritance hierarchy, so all we have to do is process all
+				 * of the relids in the list that it returns.
+				 */
+				foreach(child, children)
+				{
+					Oid			childrelid = lfirst_oid(child);
+					Relation	childrel;
+
+					if (childrelid == relid)
+						continue;
+					/* find_all_inheritors already got lock */
+					childrel = relation_open(childrelid, NoLock);
+					CheckTableNotInUse(childrel, "ALTER TABLE");
+					ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
+					relation_close(childrel, NoLock);
+				}
+			}
+			break;
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 }
 
@@ -5773,47 +6065,62 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation,
 		rel = relation_open(pg_depend->objid, AccessShareLock);
 		att = TupleDescAttr(rel->rd_att, pg_depend->objsubid - 1);
 
-		if (rel->rd_rel->relkind == RELKIND_RELATION ||
-			rel->rd_rel->relkind == RELKIND_MATVIEW ||
-			rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		{
-			if (origTypeName)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
-								origTypeName,
-								RelationGetRelationName(rel),
-								NameStr(att->attname))));
-			else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
-								RelationGetRelationName(origRelation),
-								RelationGetRelationName(rel),
-								NameStr(att->attname))));
-			else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
-								RelationGetRelationName(origRelation),
-								RelationGetRelationName(rel),
-								NameStr(att->attname))));
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
-								RelationGetRelationName(origRelation),
-								RelationGetRelationName(rel),
-								NameStr(att->attname))));
-		}
-		else if (OidIsValid(rel->rd_rel->reltype))
+		switch ((RelKind) rel->rd_rel->relkind)
 		{
-			/*
-			 * A view or composite type itself isn't a problem, but we must
-			 * recursively check for indirect dependencies via its rowtype.
-			 */
-			find_composite_type_dependencies(rel->rd_rel->reltype,
-											 origRelation, origTypeName);
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+				{
+					if (origTypeName)
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
+										origTypeName,
+										RelationGetRelationName(rel),
+										NameStr(att->attname))));
+					else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
+										RelationGetRelationName(origRelation),
+										RelationGetRelationName(rel),
+										NameStr(att->attname))));
+					else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
+										RelationGetRelationName(origRelation),
+										RelationGetRelationName(rel),
+										NameStr(att->attname))));
+					else
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
+										RelationGetRelationName(origRelation),
+										RelationGetRelationName(rel),
+										NameStr(att->attname))));
+				}
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				if (OidIsValid(rel->rd_rel->reltype))
+				{
+					/*
+					 * A view or composite type itself isn't a problem, but we
+					 * must recursively check for indirect dependencies via
+					 * its rowtype.
+					 */
+					find_composite_type_dependencies(rel->rd_rel->reltype,
+													 origRelation, origTypeName);
+				}
+				break;
 		}
 
 		relation_close(rel, AccessShareLock);
@@ -5934,8 +6241,24 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("cannot add column to typed table")));
 
-	if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-		ATTypedTableRecursion(wqueue, rel, cmd, lockmode, context);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_COMPOSITE_TYPE:
+			ATTypedTableRecursion(wqueue, rel, cmd, lockmode, context);
+			break;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	if (recurse && !is_view)
 		cmd->subtype = AT_AddColumnRecurse;
@@ -6455,16 +6778,32 @@ ATPrepDropNotNull(Relation rel, bool recurse, bool recursing)
 	 * If the parent is a partitioned table, like check constraints, we do not
 	 * support removing the NOT NULL while partitions exist.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		PartitionDesc partdesc = RelationGetPartitionDesc(rel);
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				PartitionDesc partdesc = RelationGetPartitionDesc(rel);
 
-		Assert(partdesc != NULL);
-		if (partdesc->nparts > 0 && !recurse && !recursing)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-					 errmsg("cannot remove constraint from only the partitioned table when partitions exist"),
-					 errhint("Do not specify the ONLY keyword.")));
+				Assert(partdesc != NULL);
+				if (partdesc->nparts > 0 && !recurse && !recursing)
+					ereport(ERROR,
+							(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+							 errmsg("cannot remove constraint from only the partitioned table when partitions exist"),
+							 errhint("Do not specify the ONLY keyword.")));
+			}
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 }
 
@@ -6614,17 +6953,33 @@ ATPrepSetNotNull(List **wqueue, Relation rel,
 	 * apply ALTER TABLE ... CHECK NOT NULL to every child.  Otherwise, use
 	 * normal recursion logic.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
-		!recurse)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		AlterTableCmd *newcmd = makeNode(AlterTableCmd);
+		case RELKIND_PARTITIONED_TABLE:
+			if (!recurse)
+			{
+				AlterTableCmd *newcmd = makeNode(AlterTableCmd);
 
-		newcmd->subtype = AT_CheckNotNull;
-		newcmd->name = pstrdup(cmd->name);
-		ATSimpleRecursion(wqueue, rel, newcmd, true, lockmode, context);
+				newcmd->subtype = AT_CheckNotNull;
+				newcmd->name = pstrdup(cmd->name);
+				ATSimpleRecursion(wqueue, rel, newcmd, true, lockmode, context);
+				break;
+			}
+			/* fallthrough */
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
+			break;
 	}
-	else
-		ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
 }
 
 /*
@@ -7249,12 +7604,27 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
 	 * We allow referencing columns by numbers only for indexes, since table
 	 * column numbers could contain gaps if columns are later dropped.
 	 */
-	if (rel->rd_rel->relkind != RELKIND_INDEX &&
-		rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX &&
-		!colName)
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("cannot refer to non-index column by number")));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			if (!colName)
+				ereport(ERROR,
+						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 errmsg("cannot refer to non-index column by number")));
+			break;
+	}
 
 	Assert(IsA(newValue, Integer));
 	newtarget = intVal(newValue);
@@ -7310,20 +7680,35 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
 				 errmsg("cannot alter system column \"%s\"",
 						colName)));
 
-	if (rel->rd_rel->relkind == RELKIND_INDEX ||
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		if (attnum > rel->rd_index->indnkeyatts)
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot alter statistics on included column \"%s\" of index \"%s\"",
-							NameStr(attrtuple->attname), RelationGetRelationName(rel))));
-		else if (rel->rd_index->indkey.values[attnum - 1] != 0)
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot alter statistics on non-expression column \"%s\" of index \"%s\"",
-							NameStr(attrtuple->attname), RelationGetRelationName(rel)),
-					 errhint("Alter statistics on table column instead.")));
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			{
+				if (attnum > rel->rd_index->indnkeyatts)
+					ereport(ERROR,
+							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							 errmsg("cannot alter statistics on included column \"%s\" of index \"%s\"",
+									NameStr(attrtuple->attname), RelationGetRelationName(rel))));
+				else if (rel->rd_index->indkey.values[attnum - 1] != 0)
+					ereport(ERROR,
+							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							 errmsg("cannot alter statistics on non-expression column \"%s\" of index \"%s\"",
+									NameStr(attrtuple->attname), RelationGetRelationName(rel)),
+							 errhint("Alter statistics on table column instead.")));
+			}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	attrtuple->attstattarget = newtarget;
@@ -7566,8 +7951,24 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("cannot drop column from typed table")));
 
-	if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-		ATTypedTableRecursion(wqueue, rel, cmd, lockmode, context);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_COMPOSITE_TYPE:
+			ATTypedTableRecursion(wqueue, rel, cmd, lockmode, context);
+			break;
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	if (recurse)
 		cmd->subtype = AT_DropColumnRecurse;
@@ -7676,15 +8077,32 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
 		Relation	attr_rel;
 		ListCell   *child;
 
-		/*
-		 * In case of a partitioned table, the column must be dropped from the
-		 * partitions as well.
-		 */
-		if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !recurse)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-					 errmsg("cannot drop column from only the partitioned table when partitions exist"),
-					 errhint("Do not specify the ONLY keyword.")));
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+				/*
+				 * In case of a partitioned table, the column must be dropped
+				 * from the partitions as well.
+				 */
+			case RELKIND_PARTITIONED_TABLE:
+				if (!recurse)
+					ereport(ERROR,
+							(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+							 errmsg("cannot drop column from only the partitioned table when partitions exist"),
+							 errhint("Do not specify the ONLY keyword.")));
+				break;
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
 		foreach(child, children)
@@ -7861,10 +8279,26 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
 	 * Doing this on partitioned tables is not a simple feature to implement,
 	 * so let's punt for now.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables")));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables")));
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	indexRel = index_open(index_oid, AccessShareLock);
 
@@ -8218,30 +8652,44 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	 * Validity checks (permission checks wait till we have the column
 	 * numbers)
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		if (!recurse)
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				if (!recurse)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"",
+									RelationGetRelationName(rel),
+									RelationGetRelationName(pkrel))));
+				if (fkconstraint->skip_validation && !fkconstraint->initially_valid)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"",
+									RelationGetRelationName(rel),
+									RelationGetRelationName(pkrel)),
+							 errdetail("This feature is not yet supported on partitioned tables.")));
+			}
+			break;
+		case RELKIND_RELATION:
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"",
-							RelationGetRelationName(rel),
+					 errmsg("referenced relation \"%s\" is not a table",
 							RelationGetRelationName(pkrel))));
-		if (fkconstraint->skip_validation && !fkconstraint->initially_valid)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"",
-							RelationGetRelationName(rel),
-							RelationGetRelationName(pkrel)),
-					 errdetail("This feature is not yet supported on partitioned tables.")));
+			break;
 	}
 
-	if (pkrel->rd_rel->relkind != RELKIND_RELATION &&
-		pkrel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("referenced relation \"%s\" is not a table",
-						RelationGetRelationName(pkrel))));
-
 	if (!allowSystemTableMods && IsSystemRelation(pkrel))
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -8640,12 +9088,26 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
 	 * Verify relkind for each referenced partition.  At the top level, this
 	 * is redundant with a previous check, but we need it when recursing.
 	 */
-	if (pkrel->rd_rel->relkind != RELKIND_RELATION &&
-		pkrel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("referenced relation \"%s\" is not a table",
-						RelationGetRelationName(pkrel))));
+	switch ((RelKind) pkrel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("referenced relation \"%s\" is not a table",
+							RelationGetRelationName(pkrel))));
+	}
 
 	/*
 	 * Caller supplies us with a constraint name; however, it may be used in
@@ -8675,7 +9137,23 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
 		/*
 		 * always inherit for partitioned tables, never for legacy inheritance
 		 */
-		connoinherit = rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE;
+		switch ((RelKind) rel->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				connoinherit = false;
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				connoinherit = true;
+		}
 	}
 
 	/*
@@ -8730,69 +9208,84 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
 	/* make new constraint visible, in case we add more */
 	CommandCounterIncrement();
 
-	/*
-	 * If the referenced table is a plain relation, create the action triggers
-	 * that enforce the constraint.
-	 */
-	if (pkrel->rd_rel->relkind == RELKIND_RELATION)
-	{
-		createForeignKeyActionTriggers(rel, RelationGetRelid(pkrel),
-									   fkconstraint,
-									   constrOid, indexOid);
-	}
-
-	/*
-	 * If the referenced table is partitioned, recurse on ourselves to handle
-	 * each partition.  We need one pg_constraint row created for each
-	 * partition in addition to the pg_constraint row for the parent table.
-	 */
-	if (pkrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) pkrel->rd_rel->relkind)
 	{
-		PartitionDesc pd = RelationGetPartitionDesc(pkrel);
-
-		for (int i = 0; i < pd->nparts; i++)
-		{
-			Relation	partRel;
-			AttrMap    *map;
-			AttrNumber *mapped_pkattnum;
-			Oid			partIndexId;
-
-			partRel = table_open(pd->oids[i], ShareRowExclusiveLock);
+			/*
+			 * If the referenced table is a plain relation, create the action
+			 * triggers that enforce the constraint.
+			 */
+		case RELKIND_RELATION:
+			createForeignKeyActionTriggers(rel, RelationGetRelid(pkrel),
+										   fkconstraint,
+										   constrOid, indexOid);
+			break;
 
 			/*
-			 * Map the attribute numbers in the referenced side of the FK
-			 * definition to match the partition's column layout.
+			 * If the referenced table is partitioned, recurse on ourselves to
+			 * handle each partition.  We need one pg_constraint row created
+			 * for each partition in addition to the pg_constraint row for the
+			 * parent table.
 			 */
-			map = build_attrmap_by_name_if_req(RelationGetDescr(partRel),
-											   RelationGetDescr(pkrel));
-			if (map)
-			{
-				mapped_pkattnum = palloc(sizeof(AttrNumber) * numfks);
-				for (int j = 0; j < numfks; j++)
-					mapped_pkattnum[j] = map->attnums[pkattnum[j] - 1];
-			}
-			else
-				mapped_pkattnum = pkattnum;
-
-			/* do the deed */
-			partIndexId = index_get_partition(partRel, indexOid);
-			if (!OidIsValid(partIndexId))
-				elog(ERROR, "index for %u not found in partition %s",
-					 indexOid, RelationGetRelationName(partRel));
-			addFkRecurseReferenced(wqueue, fkconstraint, rel, partRel,
-								   partIndexId, constrOid, numfks,
-								   mapped_pkattnum, fkattnum,
-								   pfeqoperators, ppeqoperators, ffeqoperators,
-								   old_check_ok);
-
-			/* Done -- clean up (but keep the lock) */
-			table_close(partRel, NoLock);
-			if (map)
+		case RELKIND_PARTITIONED_TABLE:
 			{
-				pfree(mapped_pkattnum);
-				free_attrmap(map);
+				PartitionDesc pd = RelationGetPartitionDesc(pkrel);
+
+				for (int i = 0; i < pd->nparts; i++)
+				{
+					Relation	partRel;
+					AttrMap    *map;
+					AttrNumber *mapped_pkattnum;
+					Oid			partIndexId;
+
+					partRel = table_open(pd->oids[i], ShareRowExclusiveLock);
+
+					/*
+					 * Map the attribute numbers in the referenced side of the
+					 * FK definition to match the partition's column layout.
+					 */
+					map = build_attrmap_by_name_if_req(RelationGetDescr(partRel),
+													   RelationGetDescr(pkrel));
+					if (map)
+					{
+						mapped_pkattnum = palloc(sizeof(AttrNumber) * numfks);
+						for (int j = 0; j < numfks; j++)
+							mapped_pkattnum[j] = map->attnums[pkattnum[j] - 1];
+					}
+					else
+						mapped_pkattnum = pkattnum;
+
+					/* do the deed */
+					partIndexId = index_get_partition(partRel, indexOid);
+					if (!OidIsValid(partIndexId))
+						elog(ERROR, "index for %u not found in partition %s",
+							 indexOid, RelationGetRelationName(partRel));
+					addFkRecurseReferenced(wqueue, fkconstraint, rel, partRel,
+										   partIndexId, constrOid, numfks,
+										   mapped_pkattnum, fkattnum,
+										   pfeqoperators, ppeqoperators, ffeqoperators,
+										   old_check_ok);
+
+					/* Done -- clean up (but keep the lock) */
+					table_close(partRel, NoLock);
+					if (map)
+					{
+						pfree(mapped_pkattnum);
+						free_attrmap(map);
+					}
+				}
 			}
-		}
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	return address;
@@ -8836,177 +9329,196 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
 {
 	AssertArg(OidIsValid(parentConstr));
 
-	if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("foreign key constraints are not supported on foreign tables")));
-
-	/*
-	 * If the referencing relation is a plain table, add the check triggers to
-	 * it and, if necessary, schedule it to be checked in Phase 3.
-	 *
-	 * If the relation is partitioned, drill down to do it to its partitions.
-	 */
-	if (rel->rd_rel->relkind == RELKIND_RELATION)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		createForeignKeyCheckTriggers(RelationGetRelid(rel),
-									  RelationGetRelid(pkrel),
-									  fkconstraint,
-									  parentConstr,
-									  indexOid);
-
-		/*
-		 * Tell Phase 3 to check that the constraint is satisfied by existing
-		 * rows. We can skip this during table creation, when requested
-		 * explicitly by specifying NOT VALID in an ADD FOREIGN KEY command,
-		 * and when we're recreating a constraint following a SET DATA TYPE
-		 * operation that did not impugn its validity.
-		 */
-		if (wqueue && !old_check_ok && !fkconstraint->skip_validation)
-		{
-			NewConstraint *newcon;
-			AlteredTableInfo *tab;
+			/*
+			 * If the referencing relation is a plain table, add the check
+			 * triggers to it and, if necessary, schedule it to be checked in
+			 * Phase 3.
+			 *
+			 * If the relation is partitioned, drill down to do it to its
+			 * partitions.
+			 */
+		case RELKIND_RELATION:
+			{
+				createForeignKeyCheckTriggers(RelationGetRelid(rel),
+											  RelationGetRelid(pkrel),
+											  fkconstraint,
+											  parentConstr,
+											  indexOid);
 
-			tab = ATGetQueueEntry(wqueue, rel);
+				/*
+				 * Tell Phase 3 to check that the constraint is satisfied by
+				 * existing rows. We can skip this during table creation, when
+				 * requested explicitly by specifying NOT VALID in an ADD
+				 * FOREIGN KEY command, and when we're recreating a constraint
+				 * following a SET DATA TYPE operation that did not impugn its
+				 * validity.
+				 */
+				if (wqueue && !old_check_ok && !fkconstraint->skip_validation)
+				{
+					NewConstraint *newcon;
+					AlteredTableInfo *tab;
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
-			newcon->name = get_constraint_name(parentConstr);
-			newcon->contype = CONSTR_FOREIGN;
-			newcon->refrelid = RelationGetRelid(pkrel);
-			newcon->refindid = indexOid;
-			newcon->conid = parentConstr;
-			newcon->qual = (Node *) fkconstraint;
+					tab = ATGetQueueEntry(wqueue, rel);
 
-			tab->constraints = lappend(tab->constraints, newcon);
-		}
-	}
-	else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-	{
-		PartitionDesc pd = RelationGetPartitionDesc(rel);
+					newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+					newcon->name = get_constraint_name(parentConstr);
+					newcon->contype = CONSTR_FOREIGN;
+					newcon->refrelid = RelationGetRelid(pkrel);
+					newcon->refindid = indexOid;
+					newcon->conid = parentConstr;
+					newcon->qual = (Node *) fkconstraint;
 
-		/*
-		 * Recurse to take appropriate action on each partition; either we
-		 * find an existing constraint to reparent to ours, or we create a new
-		 * one.
-		 */
-		for (int i = 0; i < pd->nparts; i++)
-		{
-			Oid			partitionId = pd->oids[i];
-			Relation	partition = table_open(partitionId, lockmode);
-			List	   *partFKs;
-			AttrMap    *attmap;
-			AttrNumber	mapped_fkattnum[INDEX_MAX_KEYS];
-			bool		attached;
-			char	   *conname;
-			Oid			constrOid;
-			ObjectAddress address,
-						referenced;
-			ListCell   *cell;
-
-			CheckTableNotInUse(partition, "ALTER TABLE");
-
-			attmap = build_attrmap_by_name(RelationGetDescr(partition),
-										   RelationGetDescr(rel));
-			for (int j = 0; j < numfks; j++)
-				mapped_fkattnum[j] = attmap->attnums[fkattnum[j] - 1];
-
-			/* Check whether an existing constraint can be repurposed */
-			partFKs = copyObject(RelationGetFKeyList(partition));
-			attached = false;
-			foreach(cell, partFKs)
-			{
-				ForeignKeyCacheInfo *fk;
-
-				fk = lfirst_node(ForeignKeyCacheInfo, cell);
-				if (tryAttachPartitionForeignKey(fk,
-												 partitionId,
-												 parentConstr,
-												 numfks,
-												 mapped_fkattnum,
-												 pkattnum,
-												 pfeqoperators))
-				{
-					attached = true;
-					break;
+					tab->constraints = lappend(tab->constraints, newcon);
 				}
 			}
-			if (attached)
+			break;
+		case RELKIND_PARTITIONED_TABLE:
 			{
-				table_close(partition, NoLock);
-				continue;
-			}
+				PartitionDesc pd = RelationGetPartitionDesc(rel);
 
-			/*
-			 * No luck finding a good constraint to reuse; create our own.
-			 */
-			if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
-									 RelationGetRelid(partition),
-									 fkconstraint->conname))
-				conname = ChooseConstraintName(RelationGetRelationName(partition),
-											   ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs),
-											   "fkey",
-											   RelationGetNamespace(partition), NIL);
-			else
-				conname = fkconstraint->conname;
-			constrOid =
-				CreateConstraintEntry(conname,
-									  RelationGetNamespace(partition),
-									  CONSTRAINT_FOREIGN,
-									  fkconstraint->deferrable,
-									  fkconstraint->initdeferred,
-									  fkconstraint->initially_valid,
-									  parentConstr,
-									  partitionId,
-									  mapped_fkattnum,
-									  numfks,
-									  numfks,
-									  InvalidOid,
-									  indexOid,
-									  RelationGetRelid(pkrel),
-									  pkattnum,
-									  pfeqoperators,
-									  ppeqoperators,
-									  ffeqoperators,
-									  numfks,
-									  fkconstraint->fk_upd_action,
-									  fkconstraint->fk_del_action,
-									  fkconstraint->fk_matchtype,
-									  NULL,
-									  NULL,
-									  NULL,
-									  false,
-									  1,
-									  false,
-									  false);
+				/*
+				 * Recurse to take appropriate action on each partition;
+				 * either we find an existing constraint to reparent to ours,
+				 * or we create a new one.
+				 */
+				for (int i = 0; i < pd->nparts; i++)
+				{
+					Oid			partitionId = pd->oids[i];
+					Relation	partition = table_open(partitionId, lockmode);
+					List	   *partFKs;
+					AttrMap    *attmap;
+					AttrNumber	mapped_fkattnum[INDEX_MAX_KEYS];
+					bool		attached;
+					char	   *conname;
+					Oid			constrOid;
+					ObjectAddress address,
+								referenced;
+					ListCell   *cell;
+
+					CheckTableNotInUse(partition, "ALTER TABLE");
+
+					attmap = build_attrmap_by_name(RelationGetDescr(partition),
+												   RelationGetDescr(rel));
+					for (int j = 0; j < numfks; j++)
+						mapped_fkattnum[j] = attmap->attnums[fkattnum[j] - 1];
+
+					/* Check whether an existing constraint can be repurposed */
+					partFKs = copyObject(RelationGetFKeyList(partition));
+					attached = false;
+					foreach(cell, partFKs)
+					{
+						ForeignKeyCacheInfo *fk;
+
+						fk = lfirst_node(ForeignKeyCacheInfo, cell);
+						if (tryAttachPartitionForeignKey(fk,
+														 partitionId,
+														 parentConstr,
+														 numfks,
+														 mapped_fkattnum,
+														 pkattnum,
+														 pfeqoperators))
+						{
+							attached = true;
+							break;
+						}
+					}
+					if (attached)
+					{
+						table_close(partition, NoLock);
+						continue;
+					}
 
-			/*
-			 * Give this constraint partition-type dependencies on the parent
-			 * constraint as well as the table.
-			 */
-			ObjectAddressSet(address, ConstraintRelationId, constrOid);
-			ObjectAddressSet(referenced, ConstraintRelationId, parentConstr);
-			recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_PRI);
-			ObjectAddressSet(referenced, RelationRelationId, partitionId);
-			recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_SEC);
+					/*
+					 * No luck finding a good constraint to reuse; create our
+					 * own.
+					 */
+					if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
+											 RelationGetRelid(partition),
+											 fkconstraint->conname))
+						conname = ChooseConstraintName(RelationGetRelationName(partition),
+													   ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs),
+													   "fkey",
+													   RelationGetNamespace(partition), NIL);
+					else
+						conname = fkconstraint->conname;
+					constrOid =
+						CreateConstraintEntry(conname,
+											  RelationGetNamespace(partition),
+											  CONSTRAINT_FOREIGN,
+											  fkconstraint->deferrable,
+											  fkconstraint->initdeferred,
+											  fkconstraint->initially_valid,
+											  parentConstr,
+											  partitionId,
+											  mapped_fkattnum,
+											  numfks,
+											  numfks,
+											  InvalidOid,
+											  indexOid,
+											  RelationGetRelid(pkrel),
+											  pkattnum,
+											  pfeqoperators,
+											  ppeqoperators,
+											  ffeqoperators,
+											  numfks,
+											  fkconstraint->fk_upd_action,
+											  fkconstraint->fk_del_action,
+											  fkconstraint->fk_matchtype,
+											  NULL,
+											  NULL,
+											  NULL,
+											  false,
+											  1,
+											  false,
+											  false);
 
-			/* Make all this visible before recursing */
-			CommandCounterIncrement();
+					/*
+					 * Give this constraint partition-type dependencies on the
+					 * parent constraint as well as the table.
+					 */
+					ObjectAddressSet(address, ConstraintRelationId, constrOid);
+					ObjectAddressSet(referenced, ConstraintRelationId, parentConstr);
+					recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_PRI);
+					ObjectAddressSet(referenced, RelationRelationId, partitionId);
+					recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_SEC);
 
-			/* call ourselves to finalize the creation and we're done */
-			addFkRecurseReferencing(wqueue, fkconstraint, partition, pkrel,
-									indexOid,
-									constrOid,
-									numfks,
-									pkattnum,
-									mapped_fkattnum,
-									pfeqoperators,
-									ppeqoperators,
-									ffeqoperators,
-									old_check_ok,
-									lockmode);
-
-			table_close(partition, NoLock);
-		}
+					/* Make all this visible before recursing */
+					CommandCounterIncrement();
+
+					/* call ourselves to finalize the creation and we're done */
+					addFkRecurseReferencing(wqueue, fkconstraint, partition, pkrel,
+											indexOid,
+											constrOid,
+											numfks,
+											pkattnum,
+											mapped_fkattnum,
+											pfeqoperators,
+											ppeqoperators,
+											ffeqoperators,
+											old_check_ok,
+											lockmode);
+
+					table_close(partition, NoLock);
+				}
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("foreign key constraints are not supported on foreign tables")));
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 }
 
@@ -9229,10 +9741,26 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
 	if (clone == NIL)
 		return;
 
-	if (partRel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("foreign key constraints are not supported on foreign tables")));
+	switch ((RelKind) partRel->rd_rel->relkind)
+	{
+		case RELKIND_FOREIGN_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("foreign key constraints are not supported on foreign tables")));
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * The constraint key may differ, if the columns in the partition are
@@ -9282,9 +9810,25 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
 		 * relation, that means to lock all partitions.
 		 */
 		pkrel = table_open(constrForm->confrelid, ShareRowExclusiveLock);
-		if (pkrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			(void) find_all_inheritors(RelationGetRelid(pkrel),
-									   ShareRowExclusiveLock, NULL);
+		switch ((RelKind) pkrel->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				(void) find_all_inheritors(RelationGetRelid(pkrel),
+										   ShareRowExclusiveLock, NULL);
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		DeconstructFkConstraintRow(tuple, &numfks, conkey, confkey,
 								   conpfeqop, conppeqop, conffeqop);
@@ -10249,9 +10793,23 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
 	 * VALIDATE CONSTRAINT is a no-op for foreign tables and partitioned
 	 * tables.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			return;
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	constrForm = (Form_pg_constraint) GETSTRUCT(constrtup);
 
@@ -10705,11 +11263,27 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 	 * For partitioned tables, non-CHECK inherited constraints are dropped via
 	 * the dependency mechanism, so we're done here.
 	 */
-	if (contype != CONSTRAINT_CHECK &&
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		table_close(conrel, RowExclusiveLock);
-		return;
+		case RELKIND_PARTITIONED_TABLE:
+			if (contype != CONSTRAINT_CHECK)
+			{
+				table_close(conrel, RowExclusiveLock);
+				return;
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -10727,12 +11301,28 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 	 * recurse, it's a user error.  It doesn't make sense to have a constraint
 	 * be defined only on the parent, especially if it's a partitioned table.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
-		children != NIL && !recurse)
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-				 errmsg("cannot remove constraint from only the partitioned table when partitions exist"),
-				 errhint("Do not specify the ONLY keyword.")));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			if (children != NIL && !recurse)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+						 errmsg("cannot remove constraint from only the partitioned table when partitions exist"),
+						 errhint("Do not specify the ONLY keyword.")));
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	foreach(child, children)
 	{
@@ -10924,87 +11514,106 @@ ATPrepAlterColumnType(List **wqueue,
 					   list_make1_oid(rel->rd_rel->reltype),
 					   0);
 
-	if (tab->relkind == RELKIND_RELATION ||
-		tab->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) tab->relkind)
 	{
-		/*
-		 * Set up an expression to transform the old data value to the new
-		 * type. If a USING option was given, use the expression as
-		 * transformed by transformAlterTableStmt, else just take the old
-		 * value and try to coerce it.  We do this first so that type
-		 * incompatibility can be detected before we waste effort, and because
-		 * we need the expression to be parsed against the original table row
-		 * type.
-		 */
-		if (!transform)
-		{
-			transform = (Node *) makeVar(1, attnum,
-										 attTup->atttypid, attTup->atttypmod,
-										 attTup->attcollation,
-										 0);
-		}
-
-		transform = coerce_to_target_type(pstate,
-										  transform, exprType(transform),
-										  targettype, targettypmod,
-										  COERCION_ASSIGNMENT,
-										  COERCE_IMPLICIT_CAST,
-										  -1);
-		if (transform == NULL)
-		{
-			/* error text depends on whether USING was specified or not */
-			if (def->cooked_default != NULL)
-				ereport(ERROR,
-						(errcode(ERRCODE_DATATYPE_MISMATCH),
-						 errmsg("result of USING clause for column \"%s\""
-								" cannot be cast automatically to type %s",
-								colName, format_type_be(targettype)),
-						 errhint("You might need to add an explicit cast.")));
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATATYPE_MISMATCH),
-						 errmsg("column \"%s\" cannot be cast automatically to type %s",
-								colName, format_type_be(targettype)),
-				/* translator: USING is SQL, don't translate it */
-						 errhint("You might need to specify \"USING %s::%s\".",
-								 quote_identifier(colName),
-								 format_type_with_typemod(targettype,
-														  targettypmod))));
-		}
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				/*
+				 * Set up an expression to transform the old data value to the
+				 * new type. If a USING option was given, use the expression
+				 * as transformed by transformAlterTableStmt, else just take
+				 * the old value and try to coerce it.  We do this first so
+				 * that type incompatibility can be detected before we waste
+				 * effort, and because we need the expression to be parsed
+				 * against the original table row type.
+				 */
+				if (!transform)
+				{
+					transform = (Node *) makeVar(1, attnum,
+												 attTup->atttypid, attTup->atttypmod,
+												 attTup->attcollation,
+												 0);
+				}
 
-		/* Fix collations after all else */
-		assign_expr_collations(pstate, transform);
+				transform = coerce_to_target_type(pstate,
+												  transform, exprType(transform),
+												  targettype, targettypmod,
+												  COERCION_ASSIGNMENT,
+												  COERCE_IMPLICIT_CAST,
+												  -1);
+				if (transform == NULL)
+				{
+					/*
+					 * error text depends on whether USING was specified or
+					 * not
+					 */
+					if (def->cooked_default != NULL)
+						ereport(ERROR,
+								(errcode(ERRCODE_DATATYPE_MISMATCH),
+								 errmsg("result of USING clause for column \"%s\""
+										" cannot be cast automatically to type %s",
+										colName, format_type_be(targettype)),
+								 errhint("You might need to add an explicit cast.")));
+					else
+						ereport(ERROR,
+								(errcode(ERRCODE_DATATYPE_MISMATCH),
+								 errmsg("column \"%s\" cannot be cast automatically to type %s",
+										colName, format_type_be(targettype)),
+						/* translator: USING is SQL, don't translate it */
+								 errhint("You might need to specify \"USING %s::%s\".",
+										 quote_identifier(colName),
+										 format_type_with_typemod(targettype,
+																  targettypmod))));
+				}
 
-		/* Plan the expr now so we can accurately assess the need to rewrite. */
-		transform = (Node *) expression_planner((Expr *) transform);
+				/* Fix collations after all else */
+				assign_expr_collations(pstate, transform);
 
-		/*
-		 * Add a work queue item to make ATRewriteTable update the column
-		 * contents.
-		 */
-		newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
-		newval->attnum = attnum;
-		newval->expr = (Expr *) transform;
-		newval->is_generated = false;
+				/*
+				 * Plan the expr now so we can accurately assess the need to
+				 * rewrite.
+				 */
+				transform = (Node *) expression_planner((Expr *) transform);
 
-		tab->newvals = lappend(tab->newvals, newval);
-		if (ATColumnChangeRequiresRewrite(transform, attnum))
-			tab->rewrite |= AT_REWRITE_COLUMN_REWRITE;
-	}
-	else if (transform)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table",
-						RelationGetRelationName(rel))));
+				/*
+				 * Add a work queue item to make ATRewriteTable update the
+				 * column contents.
+				 */
+				newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+				newval->attnum = attnum;
+				newval->expr = (Expr *) transform;
+				newval->is_generated = false;
+
+				tab->newvals = lappend(tab->newvals, newval);
+				if (ATColumnChangeRequiresRewrite(transform, attnum))
+					tab->rewrite |= AT_REWRITE_COLUMN_REWRITE;
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
 
-	if (tab->relkind == RELKIND_COMPOSITE_TYPE ||
-		tab->relkind == RELKIND_FOREIGN_TABLE)
-	{
-		/*
-		 * For composite types, do this check now.  Tables will check it later
-		 * when the table is being rewritten.
-		 */
-		find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
+			/*
+			 * For composite types, do this check now.  Tables will check it
+			 * later when the table is being rewritten.
+			 */
+			if (!transform)
+				find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
+			/* fallthrough */
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			if (transform)
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is not a table",
+								RelationGetRelationName(rel))));
+			break;
 	}
 
 	ReleaseSysCache(tuple);
@@ -11108,8 +11717,24 @@ ATPrepAlterColumnType(List **wqueue,
 				 errmsg("type of inherited column \"%s\" must be changed in child tables too",
 						colName)));
 
-	if (tab->relkind == RELKIND_COMPOSITE_TYPE)
-		ATTypedTableRecursion(wqueue, rel, cmd, lockmode, context);
+	switch ((RelKind) tab->relkind)
+	{
+		case RELKIND_COMPOSITE_TYPE:
+			ATTypedTableRecursion(wqueue, rel, cmd, lockmode, context);
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 }
 
 /*
@@ -11326,44 +11951,53 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
 				{
 					char		relKind = get_rel_relkind(foundObject.objectId);
 
-					if (relKind == RELKIND_INDEX ||
-						relKind == RELKIND_PARTITIONED_INDEX)
-					{
-						Assert(foundObject.objectSubId == 0);
-						RememberIndexForRebuilding(foundObject.objectId, tab);
-					}
-					else if (relKind == RELKIND_SEQUENCE)
-					{
-						/*
-						 * This must be a SERIAL column's sequence.  We need
-						 * not do anything to it.
-						 */
-						Assert(foundObject.objectSubId == 0);
-					}
-					else if (relKind == RELKIND_RELATION &&
-							 foundObject.objectSubId != 0 &&
-							 get_attgenerated(foundObject.objectId, foundObject.objectSubId))
-					{
-						/*
-						 * Changing the type of a column that is used by a
-						 * generated column is not allowed by SQL standard. It
-						 * might be doable with some thinking and effort.
-						 */
-						ereport(ERROR,
-								(errcode(ERRCODE_SYNTAX_ERROR),
-								 errmsg("cannot alter type of a column used by a generated column"),
-								 errdetail("Column \"%s\" is used by generated column \"%s\".",
-										   colName, get_attname(foundObject.objectId, foundObject.objectSubId, false))));
-					}
-					else
+					switch ((RelKind) relKind)
 					{
-						/* Not expecting any other direct dependencies... */
-						elog(ERROR, "unexpected object depending on column: %s",
-							 getObjectDescription(&foundObject));
+						case RELKIND_INDEX:
+						case RELKIND_PARTITIONED_INDEX:
+							Assert(foundObject.objectSubId == 0);
+							RememberIndexForRebuilding(foundObject.objectId, tab);
+							break;
+						case RELKIND_SEQUENCE:
+
+							/*
+							 * This must be a SERIAL column's sequence.  We
+							 * need not do anything to it.
+							 */
+							Assert(foundObject.objectSubId == 0);
+							break;
+						case RELKIND_RELATION:
+							if (foundObject.objectSubId != 0 &&
+								get_attgenerated(foundObject.objectId, foundObject.objectSubId))
+							{
+								/*
+								 * Changing the type of a column that is used
+								 * by a generated column is not allowed by SQL
+								 * standard. It might be doable with some
+								 * thinking and effort.
+								 */
+								ereport(ERROR,
+										(errcode(ERRCODE_SYNTAX_ERROR),
+										 errmsg("cannot alter type of a column used by a generated column"),
+										 errdetail("Column \"%s\" is used by generated column \"%s\".",
+												   colName, get_attname(foundObject.objectId, foundObject.objectSubId, false))));
+							}
+							break;
+						case RELKIND_FOREIGN_TABLE:
+						case RELKIND_PARTITIONED_TABLE:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_MATVIEW:
+						case RELKIND_VIEW:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_NULL:
+						default:
+							/* Not expecting any other direct dependencies... */
+							elog(ERROR, "unexpected object depending on column: %s",
+								 getObjectDescription(&foundObject));
+							break;
 					}
-					break;
 				}
-
+				break;
 			case OCLASS_CONSTRAINT:
 				Assert(foundObject.objectSubId == 0);
 				RememberConstraintForRebuilding(foundObject.objectId, tab);
@@ -12196,13 +12830,28 @@ TryReuseIndex(Oid oldId, IndexStmt *stmt)
 	{
 		Relation	irel = index_open(oldId, NoLock);
 
-		/* If it's a partitioned index, there is no storage to share. */
-		if (irel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+		switch ((RelKind) irel->rd_rel->relkind)
 		{
-			stmt->oldNode = irel->rd_node.relNode;
-			stmt->oldCreateSubid = irel->rd_createSubid;
-			stmt->oldFirstRelfilenodeSubid = irel->rd_firstRelfilenodeSubid;
+			case RELKIND_PARTITIONED_INDEX:
+				/* If it's a partitioned index, there is no storage to share. */
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				stmt->oldNode = irel->rd_node.relNode;
+				stmt->oldCreateSubid = irel->rd_createSubid;
+				stmt->oldFirstRelfilenodeSubid = irel->rd_firstRelfilenodeSubid;
+				break;
 		}
+
 		index_close(irel, NoLock);
 	}
 }
@@ -12397,7 +13046,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
 	tuple_class = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* Can we change the ownership of this tuple? */
-	switch (tuple_class->relkind)
+	switch ((RelKind) tuple_class->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_VIEW:
@@ -12467,6 +13116,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
 			if (recursing)
 				break;
 			/* FALL THRU */
+		case RELKIND_NULL:
 		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -12554,41 +13204,82 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
 		 * none, because it's tracked for the pg_type entry instead of here;
 		 * indexes and TOAST tables don't have their own entries either.
 		 */
-		if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
-			tuple_class->relkind != RELKIND_INDEX &&
-			tuple_class->relkind != RELKIND_PARTITIONED_INDEX &&
-			tuple_class->relkind != RELKIND_TOASTVALUE)
-			changeDependencyOnOwner(RelationRelationId, relationOid,
-									newOwnerId);
+		switch ((RelKind) tuple_class->relkind)
+		{
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_TOASTVALUE:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_NULL:
+			default:
+				changeDependencyOnOwner(RelationRelationId, relationOid,
+										newOwnerId);
+				break;
+		}
 
 		/*
 		 * Also change the ownership of the table's row type, if it has one
 		 */
-		if (tuple_class->relkind != RELKIND_INDEX &&
-			tuple_class->relkind != RELKIND_PARTITIONED_INDEX)
-			AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
+		switch ((RelKind) tuple_class->relkind)
+		{
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
+				break;
+		}
 
 		/*
 		 * If we are operating on a table or materialized view, also change
 		 * the ownership of any indexes and sequences that belong to the
 		 * relation, as well as its toast table (if it has one).
 		 */
-		if (tuple_class->relkind == RELKIND_RELATION ||
-			tuple_class->relkind == RELKIND_PARTITIONED_TABLE ||
-			tuple_class->relkind == RELKIND_MATVIEW ||
-			tuple_class->relkind == RELKIND_TOASTVALUE)
+		switch ((RelKind) tuple_class->relkind)
 		{
-			List	   *index_oid_list;
-			ListCell   *i;
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+				{
+					List	   *index_oid_list;
+					ListCell   *i;
 
-			/* Find all the indexes belonging to this relation */
-			index_oid_list = RelationGetIndexList(target_rel);
+					/* Find all the indexes belonging to this relation */
+					index_oid_list = RelationGetIndexList(target_rel);
 
-			/* For each index, recursively change its ownership */
-			foreach(i, index_oid_list)
-				ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
+					/* For each index, recursively change its ownership */
+					foreach(i, index_oid_list)
+						ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
 
-			list_free(index_oid_list);
+					list_free(index_oid_list);
+				}
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/* If it has a toast table, recurse to change its ownership */
@@ -12721,11 +13412,24 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lock
 		seqRel = relation_open(depForm->objid, lockmode);
 
 		/* skip non-sequence relations */
-		if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
+		switch ((RelKind) RelationGetForm(seqRel)->relkind)
 		{
-			/* No need to keep the lock */
-			relation_close(seqRel, lockmode);
-			continue;
+			case RELKIND_SEQUENCE:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				/* No need to keep the lock */
+				relation_close(seqRel, lockmode);
+				continue;
 		}
 
 		/* We don't need to close the sequence while we alter it. */
@@ -12867,7 +13571,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 									 operation == AT_ResetRelOptions);
 
 	/* Validate */
-	switch (rel->rd_rel->relkind)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
@@ -12879,11 +13583,47 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 			break;
 		case RELKIND_VIEW:
 			(void) view_reloptions(newOptions, true);
+
+			/* Special-case validation of view options */
+			{
+				Query	   *view_query = get_view_query(rel);
+				List	   *view_options = untransformRelOptions(newOptions);
+				ListCell   *cell;
+				bool		check_option = false;
+
+				foreach(cell, view_options)
+				{
+					DefElem    *defel = (DefElem *) lfirst(cell);
+
+					if (strcmp(defel->defname, "check_option") == 0)
+						check_option = true;
+				}
+
+				/*
+				 * If the check option is specified, look to see if the view
+				 * is actually auto-updatable or not.
+				 */
+				if (check_option)
+				{
+					const char *view_updatable_error =
+					view_query_is_auto_updatable(view_query, true);
+
+					if (view_updatable_error)
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("WITH CHECK OPTION is supported only on automatically updatable views"),
+								 errhint("%s", _(view_updatable_error))));
+				}
+			}
 			break;
 		case RELKIND_INDEX:
 		case RELKIND_PARTITIONED_INDEX:
 			(void) index_reloptions(rel->rd_indam->amoptions, newOptions, true);
 			break;
+		case RELKIND_NULL:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_SEQUENCE:
 		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -12892,39 +13632,6 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 			break;
 	}
 
-	/* Special-case validation of view options */
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-	{
-		Query	   *view_query = get_view_query(rel);
-		List	   *view_options = untransformRelOptions(newOptions);
-		ListCell   *cell;
-		bool		check_option = false;
-
-		foreach(cell, view_options)
-		{
-			DefElem    *defel = (DefElem *) lfirst(cell);
-
-			if (strcmp(defel->defname, "check_option") == 0)
-				check_option = true;
-		}
-
-		/*
-		 * If the check option is specified, look to see if the view is
-		 * actually auto-updatable or not.
-		 */
-		if (check_option)
-		{
-			const char *view_updatable_error =
-			view_query_is_auto_updatable(view_query, true);
-
-			if (view_updatable_error)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("WITH CHECK OPTION is supported only on automatically updatable views"),
-						 errhint("%s", _(view_updatable_error))));
-		}
-	}
-
 	/*
 	 * All we need do here is update the pg_class row; the new options will be
 	 * propagated into relcaches during post-commit cache inval.
@@ -13109,16 +13816,26 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
 	newrnode.spcNode = newTableSpace;
 
 	/* hand off to AM to actually create the new filenode and copy the data */
-	if (rel->rd_rel->relkind == RELKIND_INDEX)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		index_copy_data(rel, newrnode);
-	}
-	else
-	{
-		Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-			   rel->rd_rel->relkind == RELKIND_MATVIEW ||
-			   rel->rd_rel->relkind == RELKIND_TOASTVALUE);
-		table_relation_copy_data(rel, &newrnode);
+		case RELKIND_INDEX:
+			index_copy_data(rel, newrnode);
+			break;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+			table_relation_copy_data(rel, &newrnode);
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			Assert(false);
+			break;
 	}
 
 	/*
@@ -13489,10 +14206,26 @@ ATPrepAddInherit(Relation child_rel)
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("cannot change inheritance of a partition")));
 
-	if (child_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot change inheritance of partitioned table")));
+	switch ((RelKind) child_rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot change inheritance of partitioned table")));
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 }
 
 /*
@@ -13541,11 +14274,27 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
 				 errmsg("cannot inherit to temporary relation of another session")));
 
 	/* Prevent partitioned tables from becoming inheritance parents */
-	if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot inherit from partitioned table \"%s\"",
-						parent->relname)));
+	switch ((RelKind) parent_rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot inherit from partitioned table \"%s\"",
+							parent->relname)));
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/* Likewise for partitions */
 	if (parent_rel->rd_rel->relispartition)
@@ -13749,8 +14498,24 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
 	parent_natts = tupleDesc->natts;
 
 	/* If parent_rel is a partitioned table, child_rel must be a partition */
-	if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		child_is_partition = true;
+	switch ((RelKind) parent_rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			child_is_partition = true;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++)
 	{
@@ -13858,8 +14623,24 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
 	tuple_desc = RelationGetDescr(catalog_relation);
 
 	/* If parent_rel is a partitioned table, child_rel must be a partition */
-	if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		child_is_partition = true;
+	switch ((RelKind) parent_rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			child_is_partition = true;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/* Outer loop scans through the parent's constraint definitions */
 	ScanKeyInit(&parent_key,
@@ -14040,8 +14821,24 @@ RemoveInheritance(Relation child_rel, Relation parent_rel)
 	bool		child_is_partition = false;
 
 	/* If parent_rel is a partitioned table, child_rel must be a partition */
-	if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		child_is_partition = true;
+	switch ((RelKind) parent_rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			child_is_partition = true;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	found = DeleteInheritsTuple(RelationGetRelid(child_rel),
 								RelationGetRelid(parent_rel));
@@ -14952,20 +15749,36 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema)
 
 	oldNspOid = RelationGetNamespace(rel);
 
-	/* If it's an owned sequence, disallow moving it by itself. */
-	if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		Oid			tableId;
-		int32		colId;
+			/* If it's an owned sequence, disallow moving it by itself. */
+		case RELKIND_SEQUENCE:
+			{
+				Oid			tableId;
+				int32		colId;
 
-		if (sequenceIsOwned(relid, DEPENDENCY_AUTO, &tableId, &colId) ||
-			sequenceIsOwned(relid, DEPENDENCY_INTERNAL, &tableId, &colId))
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot move an owned sequence into another schema"),
-					 errdetail("Sequence \"%s\" is linked to table \"%s\".",
-							   RelationGetRelationName(rel),
-							   get_rel_name(tableId))));
+				if (sequenceIsOwned(relid, DEPENDENCY_AUTO, &tableId, &colId) ||
+					sequenceIsOwned(relid, DEPENDENCY_INTERNAL, &tableId, &colId))
+					ereport(ERROR,
+							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							 errmsg("cannot move an owned sequence into another schema"),
+							 errdetail("Sequence \"%s\" is linked to table \"%s\".",
+									   RelationGetRelationName(rel),
+									   get_rel_name(tableId))));
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* Get and lock schema OID and check its permissions. */
@@ -15014,15 +15827,27 @@ AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid,
 							   nspOid, false, false, objsMoved);
 
 	/* Fix other dependent stuff */
-	if (rel->rd_rel->relkind == RELKIND_RELATION ||
-		rel->rd_rel->relkind == RELKIND_MATVIEW ||
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
-		AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
-						   objsMoved, AccessExclusiveLock);
-		AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
-								  false, objsMoved);
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+			AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
+			AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
+							   objsMoved, AccessExclusiveLock);
+			AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
+									  false, objsMoved);
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	table_close(classRel, RowExclusiveLock);
@@ -15193,11 +16018,24 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
 		seqRel = relation_open(depForm->objid, lockmode);
 
 		/* skip non-sequence relations */
-		if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
+		switch ((RelKind) RelationGetForm(seqRel)->relkind)
 		{
-			/* No need to keep the lock */
-			relation_close(seqRel, lockmode);
-			continue;
+			case RELKIND_SEQUENCE:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				/* No need to keep the lock */
+				relation_close(seqRel, lockmode);
+				continue;
 		}
 
 		/* Fix the pg_class and pg_depend entries */
@@ -15477,11 +16315,26 @@ RangeVarCallbackOwnsTable(const RangeVar *relation,
 	relkind = get_rel_relkind(relId);
 	if (!relkind)
 		return;
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
-		relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table or materialized view", relation->relname)));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table or materialized view", relation->relname)));
+			break;
+	}
 
 	/* Check permissions */
 	if (!pg_class_ownercheck(relId, GetUserId()))
@@ -15654,17 +16507,28 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
 	 * Don't allow ALTER TABLE .. SET SCHEMA on relations that can't be moved
 	 * to a different schema, such as indexes and TOAST tables.
 	 */
-	if (IsA(stmt, AlterObjectSchemaStmt) &&
-		relkind != RELKIND_RELATION &&
-		relkind != RELKIND_VIEW &&
-		relkind != RELKIND_MATVIEW &&
-		relkind != RELKIND_SEQUENCE &&
-		relkind != RELKIND_FOREIGN_TABLE &&
-		relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table",
-						rv->relname)));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			if (IsA(stmt, AlterObjectSchemaStmt))
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table",
+								rv->relname)));
+			break;
+	}
 
 	ReleaseSysCache(tuple);
 }
@@ -16139,44 +17003,60 @@ QueuePartitionConstraintValidation(List **wqueue, Relation scanrel,
 	 * validation item now; for partitioned tables, recurse to process each
 	 * partition.
 	 */
-	if (scanrel->rd_rel->relkind == RELKIND_RELATION)
+	switch ((RelKind) scanrel->rd_rel->relkind)
 	{
-		AlteredTableInfo *tab;
+		case RELKIND_RELATION:
+			{
+				AlteredTableInfo *tab;
 
-		/* Grab a work queue entry. */
-		tab = ATGetQueueEntry(wqueue, scanrel);
-		Assert(tab->partition_constraint == NULL);
-		tab->partition_constraint = (Expr *) linitial(partConstraint);
-		tab->validate_default = validate_default;
-	}
-	else if (scanrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-	{
-		PartitionDesc partdesc = RelationGetPartitionDesc(scanrel);
-		int			i;
+				/* Grab a work queue entry. */
+				tab = ATGetQueueEntry(wqueue, scanrel);
+				Assert(tab->partition_constraint == NULL);
+				tab->partition_constraint = (Expr *) linitial(partConstraint);
+				tab->validate_default = validate_default;
+			}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				PartitionDesc partdesc = RelationGetPartitionDesc(scanrel);
+				int			i;
 
-		for (i = 0; i < partdesc->nparts; i++)
-		{
-			Relation	part_rel;
-			List	   *thisPartConstraint;
+				for (i = 0; i < partdesc->nparts; i++)
+				{
+					Relation	part_rel;
+					List	   *thisPartConstraint;
 
-			/*
-			 * This is the minimum lock we need to prevent deadlocks.
-			 */
-			part_rel = table_open(partdesc->oids[i], AccessExclusiveLock);
+					/*
+					 * This is the minimum lock we need to prevent deadlocks.
+					 */
+					part_rel = table_open(partdesc->oids[i], AccessExclusiveLock);
 
-			/*
-			 * Adjust the constraint for scanrel so that it matches this
-			 * partition's attribute numbers.
-			 */
-			thisPartConstraint =
-				map_partition_varattnos(partConstraint, 1,
-										part_rel, scanrel);
-
-			QueuePartitionConstraintValidation(wqueue, part_rel,
-											   thisPartConstraint,
-											   validate_default);
-			table_close(part_rel, NoLock);	/* keep lock till commit */
-		}
+					/*
+					 * Adjust the constraint for scanrel so that it matches
+					 * this partition's attribute numbers.
+					 */
+					thisPartConstraint =
+						map_partition_varattnos(partConstraint, 1,
+												part_rel, scanrel);
+
+					QueuePartitionConstraintValidation(wqueue, part_rel,
+													   thisPartConstraint,
+													   validate_default);
+					table_close(part_rel, NoLock);	/* keep lock till commit */
+				}
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 }
 
@@ -16260,11 +17140,29 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
 				ObjectIdGetDatum(RelationGetRelid(attachrel)));
 	scan = systable_beginscan(catalog, InheritsParentIndexId, true, NULL,
 							  1, &skey);
-	if (HeapTupleIsValid(systable_getnext(scan)) &&
-		attachrel->rd_rel->relkind == RELKIND_RELATION)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot attach inheritance parent as partition")));
+
+	switch ((RelKind) attachrel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+			if (HeapTupleIsValid(systable_getnext(scan)))
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("cannot attach inheritance parent as partition")));
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
+
 	systable_endscan(scan);
 	table_close(catalog, AccessShareLock);
 
@@ -16510,26 +17408,38 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel)
 	 * before starting work, to avoid wasting the effort of building a few
 	 * non-unique indexes before coming across a unique one.
 	 */
-	if (attachrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+	switch ((RelKind) attachrel->rd_rel->relkind)
 	{
-		foreach(cell, idxes)
-		{
-			Oid			idx = lfirst_oid(cell);
-			Relation	idxRel = index_open(idx, AccessShareLock);
-
-			if (idxRel->rd_index->indisunique ||
-				idxRel->rd_index->indisprimary)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"",
-								RelationGetRelationName(attachrel),
-								RelationGetRelationName(rel)),
-						 errdetail("Table \"%s\" contains unique indexes.",
-								   RelationGetRelationName(rel))));
-			index_close(idxRel, AccessShareLock);
-		}
+		case RELKIND_FOREIGN_TABLE:
+			foreach(cell, idxes)
+			{
+				Oid			idx = lfirst_oid(cell);
+				Relation	idxRel = index_open(idx, AccessShareLock);
 
-		goto out;
+				if (idxRel->rd_index->indisunique ||
+					idxRel->rd_index->indisprimary)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"",
+									RelationGetRelationName(attachrel),
+									RelationGetRelationName(rel)),
+							 errdetail("Table \"%s\" contains unique indexes.",
+									   RelationGetRelationName(rel))));
+				index_close(idxRel, AccessShareLock);
+			}
+			goto out;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -16549,10 +17459,23 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel)
 		 * Ignore indexes in the partitioned table other than partitioned
 		 * indexes.
 		 */
-		if (idxRel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+		switch ((RelKind) idxRel->rd_rel->relkind)
 		{
-			index_close(idxRel, AccessShareLock);
-			continue;
+			case RELKIND_PARTITIONED_INDEX:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				index_close(idxRel, AccessShareLock);
+				continue;
 		}
 
 		/* construct an indexinfo to compare existing indexes against */
@@ -17089,11 +18012,27 @@ RangeVarCallbackForAttachIndex(const RangeVar *rv, Oid relOid, Oid oldRelOid,
 	if (!HeapTupleIsValid(tuple))
 		return;					/* concurrently dropped, so nothing to do */
 	classform = (Form_pg_class) GETSTRUCT(tuple);
-	if (classform->relkind != RELKIND_PARTITIONED_INDEX &&
-		classform->relkind != RELKIND_INDEX)
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				 errmsg("\"%s\" is not an index", rv->relname)));
+
+	switch ((RelKind) classform->relkind)
+	{
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+					 errmsg("\"%s\" is not an index", rv->relname)));
+			break;
+	}
 	ReleaseSysCache(tuple);
 
 	/*
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 672fccff5b..3920760e5a 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -194,106 +194,122 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 	 * Triggers must be on tables or views, and there are additional
 	 * relation-type-specific restrictions.
 	 */
-	if (rel->rd_rel->relkind == RELKIND_RELATION)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		/* Tables can't have INSTEAD OF triggers */
-		if (stmt->timing != TRIGGER_TYPE_BEFORE &&
-			stmt->timing != TRIGGER_TYPE_AFTER)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a table",
-							RelationGetRelationName(rel)),
-					 errdetail("Tables cannot have INSTEAD OF triggers.")));
-	}
-	else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-	{
-		/* Partitioned tables can't have INSTEAD OF triggers */
-		if (stmt->timing != TRIGGER_TYPE_BEFORE &&
-			stmt->timing != TRIGGER_TYPE_AFTER)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a table",
-							RelationGetRelationName(rel)),
-					 errdetail("Tables cannot have INSTEAD OF triggers.")));
+		case RELKIND_RELATION:
+			{
+				/* Tables can't have INSTEAD OF triggers */
+				if (stmt->timing != TRIGGER_TYPE_BEFORE &&
+					stmt->timing != TRIGGER_TYPE_AFTER)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a table",
+									RelationGetRelationName(rel)),
+							 errdetail("Tables cannot have INSTEAD OF triggers.")));
+			}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				/* Partitioned tables can't have INSTEAD OF triggers */
+				if (stmt->timing != TRIGGER_TYPE_BEFORE &&
+					stmt->timing != TRIGGER_TYPE_AFTER)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a table",
+									RelationGetRelationName(rel)),
+							 errdetail("Tables cannot have INSTEAD OF triggers.")));
 
-		/*
-		 * FOR EACH ROW triggers have further restrictions
-		 */
-		if (stmt->row)
-		{
-			/*
-			 * Disallow use of transition tables.
-			 *
-			 * Note that we have another restriction about transition tables
-			 * in partitions; search for 'has_superclass' below for an
-			 * explanation.  The check here is just to protect from the fact
-			 * that if we allowed it here, the creation would succeed for a
-			 * partitioned table with no partitions, but would be blocked by
-			 * the other restriction when the first partition was created,
-			 * which is very unfriendly behavior.
-			 */
-			if (stmt->transitionRels != NIL)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("\"%s\" is a partitioned table",
-								RelationGetRelationName(rel)),
-						 errdetail("Triggers on partitioned tables cannot have transition tables.")));
-		}
-	}
-	else if (rel->rd_rel->relkind == RELKIND_VIEW)
-	{
-		/*
-		 * Views can have INSTEAD OF triggers (which we check below are
-		 * row-level), or statement-level BEFORE/AFTER triggers.
-		 */
-		if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a view",
-							RelationGetRelationName(rel)),
-					 errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
-		/* Disallow TRUNCATE triggers on VIEWs */
-		if (TRIGGER_FOR_TRUNCATE(stmt->events))
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a view",
-							RelationGetRelationName(rel)),
-					 errdetail("Views cannot have TRUNCATE triggers.")));
-	}
-	else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-	{
-		if (stmt->timing != TRIGGER_TYPE_BEFORE &&
-			stmt->timing != TRIGGER_TYPE_AFTER)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a foreign table",
-							RelationGetRelationName(rel)),
-					 errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
+				/*
+				 * FOR EACH ROW triggers have further restrictions
+				 */
+				if (stmt->row)
+				{
+					/*
+					 * Disallow use of transition tables.
+					 *
+					 * Note that we have another restriction about transition
+					 * tables in partitions; search for 'has_superclass' below
+					 * for an explanation.  The check here is just to protect
+					 * from the fact that if we allowed it here, the creation
+					 * would succeed for a partitioned table with no
+					 * partitions, but would be blocked by the other
+					 * restriction when the first partition was created, which
+					 * is very unfriendly behavior.
+					 */
+					if (stmt->transitionRels != NIL)
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("\"%s\" is a partitioned table",
+										RelationGetRelationName(rel)),
+								 errdetail("Triggers on partitioned tables cannot have transition tables.")));
+				}
+			}
+			break;
+		case RELKIND_VIEW:
+			{
+				/*
+				 * Views can have INSTEAD OF triggers (which we check below
+				 * are row-level), or statement-level BEFORE/AFTER triggers.
+				 */
+				if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a view",
+									RelationGetRelationName(rel)),
+							 errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
+				/* Disallow TRUNCATE triggers on VIEWs */
+				if (TRIGGER_FOR_TRUNCATE(stmt->events))
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a view",
+									RelationGetRelationName(rel)),
+							 errdetail("Views cannot have TRUNCATE triggers.")));
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			{
+				if (stmt->timing != TRIGGER_TYPE_BEFORE &&
+					stmt->timing != TRIGGER_TYPE_AFTER)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a foreign table",
+									RelationGetRelationName(rel)),
+							 errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
 
-		if (TRIGGER_FOR_TRUNCATE(stmt->events))
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a foreign table",
-							RelationGetRelationName(rel)),
-					 errdetail("Foreign tables cannot have TRUNCATE triggers.")));
+				if (TRIGGER_FOR_TRUNCATE(stmt->events))
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a foreign table",
+									RelationGetRelationName(rel)),
+							 errdetail("Foreign tables cannot have TRUNCATE triggers.")));
 
-		/*
-		 * We disallow constraint triggers to protect the assumption that
-		 * triggers on FKs can't be deferred.  See notes with AfterTriggers
-		 * data structures, below.
-		 */
-		if (stmt->isconstraint)
+				/*
+				 * We disallow constraint triggers to protect the assumption
+				 * that triggers on FKs can't be deferred.  See notes with
+				 * AfterTriggers data structures, below.
+				 */
+				if (stmt->isconstraint)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a foreign table",
+									RelationGetRelationName(rel)),
+							 errdetail("Foreign tables cannot have constraint triggers.")));
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is a foreign table",
-							RelationGetRelationName(rel)),
-					 errdetail("Foreign tables cannot have constraint triggers.")));
+					 errmsg("\"%s\" is not a table or view",
+							RelationGetRelationName(rel))));
+			break;
 	}
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table or view",
-						RelationGetRelationName(rel))));
 
 	if (!allowSystemTableMods && IsSystemRelation(rel))
 		ereport(ERROR,
@@ -345,8 +361,26 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 	 *
 	 * For that, we'd better hold lock on all of them ahead of time.
 	 */
-	partition_recurse = !isInternal && stmt->row &&
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			partition_recurse = !isInternal && stmt->row;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			partition_recurse = false;
+			break;
+	}
+
 	if (partition_recurse)
 		list_free(find_all_inheritors(RelationGetRelid(rel),
 									  ShareRowExclusiveLock, NULL));
@@ -416,19 +450,34 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 			 * adjustments will be needed below.
 			 */
 
-			if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is a foreign table",
-								RelationGetRelationName(rel)),
-						 errdetail("Triggers on foreign tables cannot have transition tables.")));
-
-			if (rel->rd_rel->relkind == RELKIND_VIEW)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("\"%s\" is a view",
-								RelationGetRelationName(rel)),
-						 errdetail("Triggers on views cannot have transition tables.")));
+			switch ((RelKind) rel->rd_rel->relkind)
+			{
+				case RELKIND_FOREIGN_TABLE:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a foreign table",
+									RelationGetRelationName(rel)),
+							 errdetail("Triggers on foreign tables cannot have transition tables.")));
+					break;
+				case RELKIND_VIEW:
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("\"%s\" is a view",
+									RelationGetRelationName(rel)),
+							 errdetail("Triggers on views cannot have transition tables.")));
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					break;
+			}
 
 			/*
 			 * We currently don't allow row-level triggers with transition
@@ -1191,14 +1240,27 @@ RemoveTriggerById(Oid trigOid)
 
 	rel = table_open(relid, AccessExclusiveLock);
 
-	if (rel->rd_rel->relkind != RELKIND_RELATION &&
-		rel->rd_rel->relkind != RELKIND_VIEW &&
-		rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-		rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, view, or foreign table",
-						RelationGetRelationName(rel))));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table, view, or foreign table",
+							RelationGetRelationName(rel))));
+			break;
+	}
 
 	if (!allowSystemTableMods && IsSystemRelation(rel))
 		ereport(ERROR,
@@ -1298,13 +1360,27 @@ RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
 	form = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* only tables and views can have triggers */
-	if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
-		form->relkind != RELKIND_FOREIGN_TABLE &&
-		form->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, view, or foreign table",
-						rv->relname)));
+	switch ((RelKind) form->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table, view, or foreign table",
+							rv->relname)));
+			break;
+	}
 
 	/* you must own the table to rename one of its triggers */
 	if (!pg_class_ownercheck(relid, GetUserId()))
@@ -1534,21 +1610,37 @@ EnableDisableTrigger(Relation rel, const char *tgname,
 			 * When altering FOR EACH ROW triggers on a partitioned table, do
 			 * the same on the partitions as well.
 			 */
-			if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
-				(TRIGGER_FOR_ROW(oldtrig->tgtype)))
+			switch ((RelKind) rel->rd_rel->relkind)
 			{
-				PartitionDesc partdesc = RelationGetPartitionDesc(rel);
-				int			i;
-
-				for (i = 0; i < partdesc->nparts; i++)
-				{
-					Relation	part;
-
-					part = relation_open(partdesc->oids[i], lockmode);
-					EnableDisableTrigger(part, NameStr(oldtrig->tgname),
-										 fires_when, skip_system, lockmode);
-					table_close(part, NoLock);	/* keep lock till commit */
-				}
+				case RELKIND_PARTITIONED_TABLE:
+					if (TRIGGER_FOR_ROW(oldtrig->tgtype))
+					{
+						PartitionDesc partdesc = RelationGetPartitionDesc(rel);
+						int			i;
+
+						for (i = 0; i < partdesc->nparts; i++)
+						{
+							Relation	part;
+
+							part = relation_open(partdesc->oids[i], lockmode);
+							EnableDisableTrigger(part, NameStr(oldtrig->tgname),
+												 fires_when, skip_system, lockmode);
+							table_close(part, NoLock);	/* keep lock till commit */
+						}
+					}
+					break;
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_VIEW:
+				case RELKIND_SEQUENCE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 
 			changed = true;
@@ -4167,12 +4259,26 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
 						ExecDropSingleTupleTableSlot(slot2);
 						slot1 = slot2 = NULL;
 					}
-					if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+					switch ((RelKind) rel->rd_rel->relkind)
 					{
-						slot1 = MakeSingleTupleTableSlot(rel->rd_att,
-														 &TTSOpsMinimalTuple);
-						slot2 = MakeSingleTupleTableSlot(rel->rd_att,
-														 &TTSOpsMinimalTuple);
+						case RELKIND_FOREIGN_TABLE:
+							slot1 = MakeSingleTupleTableSlot(rel->rd_att,
+															 &TTSOpsMinimalTuple);
+							slot2 = MakeSingleTupleTableSlot(rel->rd_att,
+															 &TTSOpsMinimalTuple);
+							break;
+						case RELKIND_PARTITIONED_TABLE:
+						case RELKIND_RELATION:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_INDEX:
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_MATVIEW:
+						case RELKIND_VIEW:
+						case RELKIND_SEQUENCE:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_NULL:
+						default:
+							break;
 					}
 					if (trigdesc == NULL)	/* should not happen */
 						elog(ERROR, "relation %u has no triggers",
@@ -5566,9 +5672,27 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
 			break;
 	}
 
-	if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
-		new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ?
-			AFTER_TRIGGER_2CTID : AFTER_TRIGGER_1CTID;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_FOREIGN_TABLE:
+			if (row_trigger)
+				break;
+			/* fallthrough */
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ?
+				AFTER_TRIGGER_2CTID : AFTER_TRIGGER_1CTID;
+			break;
+	}
 	/* else, we'll initialize ate_flags for each trigger */
 
 	tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
@@ -5586,16 +5710,33 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
 							modifiedCols, oldslot, newslot))
 			continue;
 
-		if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
+		switch ((RelKind) relkind)
 		{
-			if (fdw_tuplestore == NULL)
-			{
-				fdw_tuplestore = GetCurrentFDWTuplestore();
-				new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
-			}
-			else
-				/* subsequent event for the same tuple */
-				new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
+			case RELKIND_FOREIGN_TABLE:
+				if (row_trigger)
+				{
+					if (fdw_tuplestore == NULL)
+					{
+						fdw_tuplestore = GetCurrentFDWTuplestore();
+						new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
+					}
+					else
+						/* subsequent event for the same tuple */
+						new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
+				}
+				break;
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/*
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 9e5938b10e..4771b8517f 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2918,11 +2918,26 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
 			 * a suitable expression index, this should also check expression
 			 * index columns.
 			 */
-			if (rel->rd_rel->relkind != RELKIND_RELATION &&
-				rel->rd_rel->relkind != RELKIND_MATVIEW)
+			switch ((RelKind) rel->rd_rel->relkind)
 			{
-				relation_close(rel, lockmode);
-				continue;
+				case RELKIND_RELATION:
+				case RELKIND_MATVIEW:
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					{
+						relation_close(rel, lockmode);
+						continue;
+					}
+					break;
 			}
 
 			/* Build the RelToCheck entry with enough space for all atts */
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index d32de23e62..15c9bcb142 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -881,10 +881,23 @@ get_all_vacuum_rels(int options)
 		 * to be performed, caller will decide whether to process or ignore
 		 * them.
 		 */
-		if (classForm->relkind != RELKIND_RELATION &&
-			classForm->relkind != RELKIND_MATVIEW &&
-			classForm->relkind != RELKIND_PARTITIONED_TABLE)
-			continue;
+		switch ((RelKind) classForm->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				continue;
+		}
 
 		/*
 		 * Build VacuumRelation(s) specifying the table OIDs to be processed.
@@ -1383,13 +1396,27 @@ vac_update_datfrozenxid(void)
 		 * Only consider relations able to hold unfrozen XIDs (anything else
 		 * should have InvalidTransactionId in relfrozenxid anyway).
 		 */
-		if (classForm->relkind != RELKIND_RELATION &&
-			classForm->relkind != RELKIND_MATVIEW &&
-			classForm->relkind != RELKIND_TOASTVALUE)
+		switch ((RelKind) classForm->relkind)
 		{
-			Assert(!TransactionIdIsValid(classForm->relfrozenxid));
-			Assert(!MultiXactIdIsValid(classForm->relminmxid));
-			continue;
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				{
+					Assert(!TransactionIdIsValid(classForm->relfrozenxid));
+					Assert(!MultiXactIdIsValid(classForm->relminmxid));
+					continue;
+				}
+				break;
 		}
 
 		/*
@@ -1762,18 +1789,31 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
 	/*
 	 * Check that it's of a vacuumable relkind.
 	 */
-	if (onerel->rd_rel->relkind != RELKIND_RELATION &&
-		onerel->rd_rel->relkind != RELKIND_MATVIEW &&
-		onerel->rd_rel->relkind != RELKIND_TOASTVALUE &&
-		onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) onerel->rd_rel->relkind)
 	{
-		ereport(WARNING,
-				(errmsg("skipping \"%s\" --- cannot vacuum non-tables or special system tables",
-						RelationGetRelationName(onerel))));
-		relation_close(onerel, lmode);
-		PopActiveSnapshot();
-		CommitTransactionCommand();
-		return false;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			{
+				ereport(WARNING,
+						(errmsg("skipping \"%s\" --- cannot vacuum non-tables or special system tables",
+								RelationGetRelationName(onerel))));
+				relation_close(onerel, lmode);
+				PopActiveSnapshot();
+				CommitTransactionCommand();
+				return false;
+			}
+			break;
 	}
 
 	/*
@@ -1796,13 +1836,26 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
 	 * useful work is on their child partitions, which have been queued up for
 	 * us separately.
 	 */
-	if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) onerel->rd_rel->relkind)
 	{
-		relation_close(onerel, lmode);
-		PopActiveSnapshot();
-		CommitTransactionCommand();
-		/* It's OK to proceed with ANALYZE on this table */
-		return true;
+		case RELKIND_PARTITIONED_TABLE:
+			relation_close(onerel, lmode);
+			PopActiveSnapshot();
+			CommitTransactionCommand();
+			/* It's OK to proceed with ANALYZE on this table */
+			return true;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 4fdffad6f3..dc2f1908bb 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1079,7 +1079,7 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
 	TriggerDesc *trigDesc = resultRel->trigdesc;
 	FdwRoutine *fdwroutine;
 
-	switch (resultRel->rd_rel->relkind)
+	switch ((RelKind) resultRel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -1193,6 +1193,10 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
 					break;
 			}
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_NULL:
 		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -1213,7 +1217,7 @@ CheckValidRowMarkRel(Relation rel, RowMarkType markType)
 {
 	FdwRoutine *fdwroutine;
 
-	switch (rel->rd_rel->relkind)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
@@ -1257,6 +1261,10 @@ CheckValidRowMarkRel(Relation rel, RowMarkType markType)
 						 errmsg("cannot lock rows in foreign table \"%s\"",
 								RelationGetRelationName(rel))));
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_NULL:
 		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -1308,10 +1316,26 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
 		resultRelInfo->ri_TrigWhenExprs = NULL;
 		resultRelInfo->ri_TrigInstrument = NULL;
 	}
-	if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
-		resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
-	else
-		resultRelInfo->ri_FdwRoutine = NULL;
+
+	switch ((RelKind) resultRelationDesc->rd_rel->relkind)
+	{
+		case RELKIND_FOREIGN_TABLE:
+			resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			resultRelInfo->ri_FdwRoutine = NULL;
+			break;
+	}
 
 	/* The following fields are set later if needed */
 	resultRelInfo->ri_FdwState = NULL;
@@ -2614,42 +2638,61 @@ EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot)
 			return false;
 
 		/* fetch requests on foreign tables must be passed to their FDW */
-		if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+		switch ((RelKind) erm->relation->rd_rel->relkind)
 		{
-			FdwRoutine *fdwroutine;
-			bool		updated = false;
+			case RELKIND_FOREIGN_TABLE:
+				{
+					FdwRoutine *fdwroutine;
+					bool		updated = false;
 
-			fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
-			/* this should have been checked already, but let's be safe */
-			if (fdwroutine->RefetchForeignRow == NULL)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("cannot lock rows in foreign table \"%s\"",
-								RelationGetRelationName(erm->relation))));
+					fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
 
-			fdwroutine->RefetchForeignRow(epqstate->recheckestate,
-										  erm,
-										  datum,
-										  slot,
-										  &updated);
-			if (TupIsNull(slot))
-				elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
+					/*
+					 * this should have been checked already, but let's be
+					 * safe
+					 */
+					if (fdwroutine->RefetchForeignRow == NULL)
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("cannot lock rows in foreign table \"%s\"",
+										RelationGetRelationName(erm->relation))));
 
-			/*
-			 * Ideally we'd insist on updated == false here, but that assumes
-			 * that FDWs can track that exactly, which they might not be able
-			 * to.  So just ignore the flag.
-			 */
-			return true;
-		}
-		else
-		{
-			/* ordinary table, fetch the tuple */
-			if (!table_tuple_fetch_row_version(erm->relation,
-											   (ItemPointer) DatumGetPointer(datum),
-											   SnapshotAny, slot))
-				elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
-			return true;
+					fdwroutine->RefetchForeignRow(epqstate->recheckestate,
+												  erm,
+												  datum,
+												  slot,
+												  &updated);
+					if (TupIsNull(slot))
+						elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
+
+					/*
+					 * Ideally we'd insist on updated == false here, but that
+					 * assumes that FDWs can track that exactly, which they
+					 * might not be able to.  So just ignore the flag.
+					 */
+					return true;
+				}
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				{
+					/* ordinary table, fetch the tuple */
+					if (!table_tuple_fetch_row_version(erm->relation,
+													   (ItemPointer) DatumGetPointer(datum),
+													   SnapshotAny, slot))
+						elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
+					return true;
+				}
+				break;
 		}
 	}
 	else
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index 8f474faed0..7a56b2d282 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -607,19 +607,34 @@ CheckSubscriptionRelkind(char relkind, const char *nspname,
 	/*
 	 * Give a more specific error for foreign tables.
 	 */
-	if (relkind == RELKIND_FOREIGN_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot use relation \"%s.%s\" as logical replication target",
-						nspname, relname),
-				 errdetail("\"%s.%s\" is a foreign table.",
-						   nspname, relname)));
-
-	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot use relation \"%s.%s\" as logical replication target",
-						nspname, relname),
-				 errdetail("\"%s.%s\" is not a table.",
-						   nspname, relname)));
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot use relation \"%s.%s\" as logical replication target",
+							nspname, relname),
+					 errdetail("\"%s.%s\" is a foreign table.",
+							   nspname, relname)));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("cannot use relation \"%s.%s\" as logical replication target",
+							nspname, relname),
+					 errdetail("\"%s.%s\" is not a table.",
+							   nspname, relname)));
+			break;
+	}
 }
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 20a4c474cc..d22817c759 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2177,56 +2177,77 @@ ExecModifyTable(PlanState *pstate)
 				bool		isNull;
 
 				relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
-				if (relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW)
+				switch ((RelKind) relkind)
 				{
-					datum = ExecGetJunkAttribute(slot,
-												 junkfilter->jf_junkAttNo,
-												 &isNull);
-					/* shouldn't ever get a null result... */
-					if (isNull)
-						elog(ERROR, "ctid is NULL");
-
-					tupleid = (ItemPointer) DatumGetPointer(datum);
-					tuple_ctid = *tupleid;	/* be sure we don't free ctid!! */
-					tupleid = &tuple_ctid;
-				}
+					case RELKIND_RELATION:
+					case RELKIND_MATVIEW:
+						{
+							datum = ExecGetJunkAttribute(slot,
+														 junkfilter->jf_junkAttNo,
+														 &isNull);
+							/* shouldn't ever get a null result... */
+							if (isNull)
+								elog(ERROR, "ctid is NULL");
+
+							tupleid = (ItemPointer) DatumGetPointer(datum);
+							tuple_ctid = *tupleid;	/* be sure we don't free
+													 * ctid!! */
+							tupleid = &tuple_ctid;
+						}
+						break;
+					case RELKIND_PARTITIONED_INDEX:
+					case RELKIND_SEQUENCE:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_FOREIGN_TABLE:
+					case RELKIND_INDEX:
+					case RELKIND_PARTITIONED_TABLE:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_VIEW:
+					case RELKIND_NULL:
+					default:
 
-				/*
-				 * Use the wholerow attribute, when available, to reconstruct
-				 * the old relation tuple.
-				 *
-				 * Foreign table updates have a wholerow attribute when the
-				 * relation has a row-level trigger.  Note that the wholerow
-				 * attribute does not carry system columns.  Foreign table
-				 * triggers miss seeing those, except that we know enough here
-				 * to set t_tableOid.  Quite separately from this, the FDW may
-				 * fetch its own junk attrs to identify the row.
-				 *
-				 * Other relevant relkinds, currently limited to views, always
-				 * have a wholerow attribute.
-				 */
-				else if (AttributeNumberIsValid(junkfilter->jf_junkAttNo))
-				{
-					datum = ExecGetJunkAttribute(slot,
-												 junkfilter->jf_junkAttNo,
-												 &isNull);
-					/* shouldn't ever get a null result... */
-					if (isNull)
-						elog(ERROR, "wholerow is NULL");
-
-					oldtupdata.t_data = DatumGetHeapTupleHeader(datum);
-					oldtupdata.t_len =
-						HeapTupleHeaderGetDatumLength(oldtupdata.t_data);
-					ItemPointerSetInvalid(&(oldtupdata.t_self));
-					/* Historically, view triggers see invalid t_tableOid. */
-					oldtupdata.t_tableOid =
-						(relkind == RELKIND_VIEW) ? InvalidOid :
-						RelationGetRelid(resultRelInfo->ri_RelationDesc);
-
-					oldtuple = &oldtupdata;
+						/*
+						 * Use the wholerow attribute, when available, to
+						 * reconstruct the old relation tuple.
+						 *
+						 * Foreign table updates have a wholerow attribute
+						 * when the relation has a row-level trigger.  Note
+						 * that the wholerow attribute does not carry system
+						 * columns.  Foreign table triggers miss seeing those,
+						 * except that we know enough here to set t_tableOid.
+						 * Quite separately from this, the FDW may fetch its
+						 * own junk attrs to identify the row.
+						 *
+						 * Other relevant relkinds, currently limited to
+						 * views, always have a wholerow attribute.
+						 */
+						if (AttributeNumberIsValid(junkfilter->jf_junkAttNo))
+						{
+							datum = ExecGetJunkAttribute(slot,
+														 junkfilter->jf_junkAttNo,
+														 &isNull);
+							/* shouldn't ever get a null result... */
+							if (isNull)
+								elog(ERROR, "wholerow is NULL");
+
+							oldtupdata.t_data = DatumGetHeapTupleHeader(datum);
+							oldtupdata.t_len =
+								HeapTupleHeaderGetDatumLength(oldtupdata.t_data);
+							ItemPointerSetInvalid(&(oldtupdata.t_self));
+
+							/*
+							 * Historically, view triggers see invalid
+							 * t_tableOid.
+							 */
+							oldtupdata.t_tableOid =
+								(relkind == RELKIND_VIEW) ? InvalidOid :
+								RelationGetRelid(resultRelInfo->ri_RelationDesc);
+
+							oldtuple = &oldtupdata;
+						}
+						else
+							Assert(relkind == RELKIND_FOREIGN_TABLE);
 				}
-				else
-					Assert(relkind == RELKIND_FOREIGN_TABLE);
 			}
 
 			/*
@@ -2697,27 +2718,40 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 					char		relkind;
 
 					relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
-					if (relkind == RELKIND_RELATION ||
-						relkind == RELKIND_MATVIEW ||
-						relkind == RELKIND_PARTITIONED_TABLE)
+					switch ((RelKind) relkind)
 					{
-						j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
-						if (!AttributeNumberIsValid(j->jf_junkAttNo))
-							elog(ERROR, "could not find junk ctid column");
-					}
-					else if (relkind == RELKIND_FOREIGN_TABLE)
-					{
-						/*
-						 * When there is a row-level trigger, there should be
-						 * a wholerow attribute.
-						 */
-						j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
-					}
-					else
-					{
-						j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
-						if (!AttributeNumberIsValid(j->jf_junkAttNo))
-							elog(ERROR, "could not find junk wholerow column");
+						case RELKIND_RELATION:
+						case RELKIND_MATVIEW:
+						case RELKIND_PARTITIONED_TABLE:
+							{
+								j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
+								if (!AttributeNumberIsValid(j->jf_junkAttNo))
+									elog(ERROR, "could not find junk ctid column");
+							}
+							break;
+						case RELKIND_FOREIGN_TABLE:
+							{
+								/*
+								 * When there is a row-level trigger, there
+								 * should be a wholerow attribute.
+								 */
+								j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
+							}
+							break;
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_SEQUENCE:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_INDEX:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_VIEW:
+						case RELKIND_NULL:
+						default:
+							{
+								j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
+								if (!AttributeNumberIsValid(j->jf_junkAttNo))
+									elog(ERROR, "could not find junk wholerow column");
+							}
+							break;
 					}
 				}
 
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index d984da25d7..6d2b587153 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -387,29 +387,42 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel,
 		switch (rel->rtekind)
 		{
 			case RTE_RELATION:
-				if (rte->relkind == RELKIND_FOREIGN_TABLE)
+				switch ((RelKind) rte->relkind)
 				{
-					/* Foreign table */
-					set_foreign_size(root, rel, rte);
-				}
-				else if (rte->relkind == RELKIND_PARTITIONED_TABLE)
-				{
-					/*
-					 * We could get here if asked to scan a partitioned table
-					 * with ONLY.  In that case we shouldn't scan any of the
-					 * partitions, so mark it as a dummy rel.
-					 */
-					set_dummy_rel_pathlist(rel);
-				}
-				else if (rte->tablesample != NULL)
-				{
-					/* Sampled relation */
-					set_tablesample_rel_size(root, rel, rte);
-				}
-				else
-				{
-					/* Plain relation */
-					set_plain_rel_size(root, rel, rte);
+					case RELKIND_FOREIGN_TABLE:
+						/* Foreign table */
+						set_foreign_size(root, rel, rte);
+						break;
+					case RELKIND_PARTITIONED_TABLE:
+
+						/*
+						 * We could get here if asked to scan a partitioned
+						 * table with ONLY.  In that case we shouldn't scan
+						 * any of the partitions, so mark it as a dummy rel.
+						 */
+						set_dummy_rel_pathlist(rel);
+						break;
+					case RELKIND_PARTITIONED_INDEX:
+					case RELKIND_SEQUENCE:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_INDEX:
+					case RELKIND_MATVIEW:
+					case RELKIND_RELATION:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_VIEW:
+					case RELKIND_NULL:
+					default:
+						if (rte->tablesample != NULL)
+						{
+							/* Sampled relation */
+							set_tablesample_rel_size(root, rel, rte);
+						}
+						else
+						{
+							/* Plain relation */
+							set_plain_rel_size(root, rel, rte);
+						}
+						break;
 				}
 				break;
 			case RTE_SUBQUERY:
@@ -484,20 +497,34 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
 		switch (rel->rtekind)
 		{
 			case RTE_RELATION:
-				if (rte->relkind == RELKIND_FOREIGN_TABLE)
-				{
-					/* Foreign table */
-					set_foreign_pathlist(root, rel, rte);
-				}
-				else if (rte->tablesample != NULL)
+				switch ((RelKind) rte->relkind)
 				{
-					/* Sampled relation */
-					set_tablesample_rel_pathlist(root, rel, rte);
-				}
-				else
-				{
-					/* Plain relation */
-					set_plain_rel_pathlist(root, rel, rte);
+					case RELKIND_FOREIGN_TABLE:
+						/* Foreign table */
+						set_foreign_pathlist(root, rel, rte);
+						break;
+					case RELKIND_PARTITIONED_INDEX:
+					case RELKIND_SEQUENCE:
+					case RELKIND_COMPOSITE_TYPE:
+					case RELKIND_INDEX:
+					case RELKIND_MATVIEW:
+					case RELKIND_PARTITIONED_TABLE:
+					case RELKIND_RELATION:
+					case RELKIND_TOASTVALUE:
+					case RELKIND_VIEW:
+					case RELKIND_NULL:
+					default:
+						if (rte->tablesample != NULL)
+						{
+							/* Sampled relation */
+							set_tablesample_rel_pathlist(root, rel, rte);
+						}
+						else
+						{
+							/* Plain relation */
+							set_plain_rel_pathlist(root, rel, rte);
+						}
+						break;
 				}
 				break;
 			case RTE_SUBQUERY:
@@ -643,13 +670,27 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
 			 * up with a separate connection, and these connections might not
 			 * be appropriately coordinated between workers and the leader.
 			 */
-			if (rte->relkind == RELKIND_FOREIGN_TABLE)
+			switch ((RelKind) rte->relkind)
 			{
-				Assert(rel->fdwroutine);
-				if (!rel->fdwroutine->IsForeignScanParallelSafe)
-					return;
-				if (!rel->fdwroutine->IsForeignScanParallelSafe(root, rel, rte))
-					return;
+				case RELKIND_FOREIGN_TABLE:
+					Assert(rel->fdwroutine);
+					if (!rel->fdwroutine->IsForeignScanParallelSafe)
+						return;
+					if (!rel->fdwroutine->IsForeignScanParallelSafe(root, rel, rte))
+						return;
+					break;
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_VIEW:
+				case RELKIND_SEQUENCE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 
 			/*
@@ -960,19 +1001,52 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 	 * that when we've created Paths for all the children, the root
 	 * partitioned table's list will contain all such indexes.
 	 */
-	if (rte->relkind == RELKIND_PARTITIONED_TABLE)
-		rel->partitioned_child_rels = list_make1_int(rti);
+	switch ((RelKind) rte->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			rel->partitioned_child_rels = list_make1_int(rti);
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * If this is a partitioned baserel, set the consider_partitionwise_join
 	 * flag; currently, we only consider partitionwise joins with the baserel
 	 * if its targetlist doesn't contain a whole-row Var.
 	 */
-	if (enable_partitionwise_join &&
-		rel->reloptkind == RELOPT_BASEREL &&
-		rte->relkind == RELKIND_PARTITIONED_TABLE &&
-		rel->attr_needed[InvalidAttrNumber - rel->min_attr] == NULL)
-		rel->consider_partitionwise_join = true;
+	switch ((RelKind) rte->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			if (enable_partitionwise_join &&
+				rel->reloptkind == RELOPT_BASEREL &&
+				rte->relkind == RELKIND_PARTITIONED_TABLE &&
+				rel->attr_needed[InvalidAttrNumber - rel->min_attr] == NULL)
+				rel->consider_partitionwise_join = true;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * Initialize to compute size estimates for whole append relation.
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 4131019fc9..de8c1073fa 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1280,10 +1280,24 @@ inheritance_planner(PlannerInfo *root)
 	 */
 	parent_rte = rt_fetch(top_parentRTindex, parse->rtable);
 	Assert(parent_rte->inh);
-	if (parent_rte->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) parent_rte->relkind)
 	{
-		nominalRelation = top_parentRTindex;
-		rootRelation = top_parentRTindex;
+		case RELKIND_PARTITIONED_TABLE:
+			nominalRelation = top_parentRTindex;
+			rootRelation = top_parentRTindex;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -2338,11 +2352,25 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
 			 * If target is a partition root table, we need to mark the
 			 * ModifyTable node appropriately for that.
 			 */
-			if (rt_fetch(parse->resultRelation, parse->rtable)->relkind ==
-				RELKIND_PARTITIONED_TABLE)
-				rootRelation = parse->resultRelation;
-			else
-				rootRelation = 0;
+			switch ((RelKind) rt_fetch(parse->resultRelation, parse->rtable)->relkind)
+			{
+				case RELKIND_PARTITIONED_TABLE:
+					rootRelation = parse->resultRelation;
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					rootRelation = 0;
+					break;
+			}
 
 			/*
 			 * Set up the WITH CHECK OPTION and RETURNING lists-of-lists, if
@@ -2765,45 +2793,58 @@ select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
 		/* If it's not a table at all, use ROW_MARK_COPY */
 		return ROW_MARK_COPY;
 	}
-	else if (rte->relkind == RELKIND_FOREIGN_TABLE)
-	{
-		/* Let the FDW select the rowmark type, if it wants to */
-		FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
-
-		if (fdwroutine->GetForeignRowMarkType != NULL)
-			return fdwroutine->GetForeignRowMarkType(rte, strength);
-		/* Otherwise, use ROW_MARK_COPY by default */
-		return ROW_MARK_COPY;
-	}
 	else
-	{
-		/* Regular table, apply the appropriate lock type */
-		switch (strength)
+		switch ((RelKind) rte->relkind)
 		{
-			case LCS_NONE:
+			case RELKIND_FOREIGN_TABLE:
+				{
+					/* Let the FDW select the rowmark type, if it wants to */
+					FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
 
-				/*
-				 * We don't need a tuple lock, only the ability to re-fetch
-				 * the row.
-				 */
-				return ROW_MARK_REFERENCE;
-				break;
-			case LCS_FORKEYSHARE:
-				return ROW_MARK_KEYSHARE;
-				break;
-			case LCS_FORSHARE:
-				return ROW_MARK_SHARE;
-				break;
-			case LCS_FORNOKEYUPDATE:
-				return ROW_MARK_NOKEYEXCLUSIVE;
-				break;
-			case LCS_FORUPDATE:
-				return ROW_MARK_EXCLUSIVE;
+					if (fdwroutine->GetForeignRowMarkType != NULL)
+						return fdwroutine->GetForeignRowMarkType(rte, strength);
+					/* Otherwise, use ROW_MARK_COPY by default */
+					return ROW_MARK_COPY;
+				}
 				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				/* Regular table, apply the appropriate lock type */
+				switch (strength)
+				{
+					case LCS_NONE:
+
+						/*
+						 * We don't need a tuple lock, only the ability to
+						 * re-fetch the row.
+						 */
+						return ROW_MARK_REFERENCE;
+						break;
+					case LCS_FORKEYSHARE:
+						return ROW_MARK_KEYSHARE;
+						break;
+					case LCS_FORSHARE:
+						return ROW_MARK_SHARE;
+						break;
+					case LCS_FORNOKEYUPDATE:
+						return ROW_MARK_NOKEYEXCLUSIVE;
+						break;
+					case LCS_FORUPDATE:
+						return ROW_MARK_EXCLUSIVE;
+						break;
+				}
+				elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
+				return ROW_MARK_EXCLUSIVE;	/* keep compiler quiet */
 		}
-		elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
-		return ROW_MARK_EXCLUSIVE;	/* keep compiler quiet */
-	}
 }
 
 /*
@@ -3142,8 +3183,25 @@ remove_useless_groupby_columns(PlannerInfo *root)
 		 * may cause duplicate rows.  This cannot happen with partitioned
 		 * tables, however.
 		 */
-		if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
-			continue;
+		switch ((RelKind) rte->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				if (rte->inh)
+					continue;
+				break;
+		}
 
 		/* Nothing to do unless this rel has multiple Vars in GROUP BY */
 		relattnos = groupbyattnos[relid];
diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c
index 3132fd35a5..1199b21154 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -129,88 +129,113 @@ expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel,
 	}
 
 	/* Scan the inheritance set and expand it */
-	if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) oldrelation->rd_rel->relkind)
 	{
-		/*
-		 * Partitioned table, so set up for partitioning.
-		 */
-		Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
-
-		/*
-		 * Recursively expand and lock the partitions.  While at it, also
-		 * extract the partition key columns of all the partitioned tables.
-		 */
-		expand_partitioned_rtentry(root, rel, rte, rti,
-								   oldrelation, oldrc, lockmode);
-	}
-	else
-	{
-		/*
-		 * Ordinary table, so process traditional-inheritance children.  (Note
-		 * that partitioned tables are not allowed to have inheritance
-		 * children, so it's not possible for both cases to apply.)
-		 */
-		List	   *inhOIDs;
-		ListCell   *l;
-
-		/* Scan for all members of inheritance set, acquire needed locks */
-		inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
-
-		/*
-		 * We used to special-case the situation where the table no longer has
-		 * any children, by clearing rte->inh and exiting.  That no longer
-		 * works, because this function doesn't get run until after decisions
-		 * have been made that depend on rte->inh.  We have to treat such
-		 * situations as normal inheritance.  The table itself should always
-		 * have been found, though.
-		 */
-		Assert(inhOIDs != NIL);
-		Assert(linitial_oid(inhOIDs) == parentOID);
-
-		/* Expand simple_rel_array and friends to hold child objects. */
-		expand_planner_arrays(root, list_length(inhOIDs));
-
-		/*
-		 * Expand inheritance children in the order the OIDs were returned by
-		 * find_all_inheritors.
-		 */
-		foreach(l, inhOIDs)
-		{
-			Oid			childOID = lfirst_oid(l);
-			Relation	newrelation;
-			RangeTblEntry *childrte;
-			Index		childRTindex;
-
-			/* Open rel if needed; we already have required locks */
-			if (childOID != parentOID)
-				newrelation = table_open(childOID, NoLock);
-			else
-				newrelation = oldrelation;
-
-			/*
-			 * It is possible that the parent table has children that are temp
-			 * tables of other backends.  We cannot safely access such tables
-			 * (because of buffering issues), and the best thing to do seems
-			 * to be to silently ignore them.
-			 */
-			if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation))
+		case RELKIND_PARTITIONED_TABLE:
 			{
-				table_close(newrelation, lockmode);
-				continue;
+				/*
+				 * Partitioned table, so set up for partitioning.
+				 */
+				Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
+
+				/*
+				 * Recursively expand and lock the partitions.  While at it,
+				 * also extract the partition key columns of all the
+				 * partitioned tables.
+				 */
+				expand_partitioned_rtentry(root, rel, rte, rti,
+										   oldrelation, oldrc, lockmode);
 			}
-
-			/* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
-			expand_single_inheritance_child(root, rte, rti, oldrelation,
-											oldrc, newrelation,
-											&childrte, &childRTindex);
-
-			/* Create the otherrel RelOptInfo too. */
-			(void) build_simple_rel(root, childRTindex, rel);
-
-			/* Close child relations, but keep locks */
-			if (childOID != parentOID)
-				table_close(newrelation, NoLock);
-		}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			{
+				/*
+				 * Ordinary table, so process traditional-inheritance
+				 * children.  (Note that partitioned tables are not allowed to
+				 * have inheritance children, so it's not possible for both
+				 * cases to apply.)
+				 */
+				List	   *inhOIDs;
+				ListCell   *l;
+
+				/*
+				 * Scan for all members of inheritance set, acquire needed
+				 * locks
+				 */
+				inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
+
+				/*
+				 * We used to special-case the situation where the table no
+				 * longer has any children, by clearing rte->inh and exiting.
+				 * That no longer works, because this function doesn't get run
+				 * until after decisions have been made that depend on
+				 * rte->inh.  We have to treat such situations as normal
+				 * inheritance.  The table itself should always have been
+				 * found, though.
+				 */
+				Assert(inhOIDs != NIL);
+				Assert(linitial_oid(inhOIDs) == parentOID);
+
+				/* Expand simple_rel_array and friends to hold child objects. */
+				expand_planner_arrays(root, list_length(inhOIDs));
+
+				/*
+				 * Expand inheritance children in the order the OIDs were
+				 * returned by find_all_inheritors.
+				 */
+				foreach(l, inhOIDs)
+				{
+					Oid			childOID = lfirst_oid(l);
+					Relation	newrelation;
+					RangeTblEntry *childrte;
+					Index		childRTindex;
+
+					/* Open rel if needed; we already have required locks */
+					if (childOID != parentOID)
+						newrelation = table_open(childOID, NoLock);
+					else
+						newrelation = oldrelation;
+
+					/*
+					 * It is possible that the parent table has children that
+					 * are temp tables of other backends.  We cannot safely
+					 * access such tables (because of buffering issues), and
+					 * the best thing to do seems to be to silently ignore
+					 * them.
+					 */
+					if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation))
+					{
+						table_close(newrelation, lockmode);
+						continue;
+					}
+
+					/*
+					 * Create RTE and AppendRelInfo, plus PlanRowMark if
+					 * needed.
+					 */
+					expand_single_inheritance_child(root, rte, rti, oldrelation,
+													oldrc, newrelation,
+													&childrte, &childRTindex);
+
+					/* Create the otherrel RelOptInfo too. */
+					(void) build_simple_rel(root, childRTindex, rel);
+
+					/* Close child relations, but keep locks */
+					if (childOID != parentOID)
+						table_close(newrelation, NoLock);
+				}
+			}
+			break;
 	}
 
 	/*
@@ -380,10 +405,26 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo,
 												childrelinfo->relids);
 
 		/* If this child is itself partitioned, recurse */
-		if (childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			expand_partitioned_rtentry(root, childrelinfo,
-									   childrte, childRTindex,
-									   childrel, top_parentrc, lockmode);
+		switch ((RelKind) childrel->rd_rel->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				expand_partitioned_rtentry(root, childrelinfo,
+										   childrte, childRTindex,
+										   childrel, top_parentrc, lockmode);
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		/* Close child relation, but keep locks */
 		table_close(childrel, NoLock);
@@ -448,13 +489,26 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
 	childrte->relid = childOID;
 	childrte->relkind = childrel->rd_rel->relkind;
 	/* A partitioned child will need to be expanded further. */
-	if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) childrte->relkind)
 	{
-		Assert(childOID != parentOID);
-		childrte->inh = true;
+		case RELKIND_PARTITIONED_TABLE:
+			Assert(childOID != parentOID);
+			childrte->inh = true;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			childrte->inh = false;
+			break;
 	}
-	else
-		childrte->inh = false;
 	childrte->requiredPerms = 0;
 	childrte->securityQuals = NIL;
 
@@ -578,7 +632,25 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
 		 * that the executor ignores them (except their existence means that
 		 * the child tables will be locked using the appropriate mode).
 		 */
-		childrc->isParent = (childrte->relkind == RELKIND_PARTITIONED_TABLE);
+		switch ((RelKind) childrte->relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+				childrc->isParent = true;
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				childrc->isParent = false;
+				break;
+		}
 
 		/* Include child's rowmark type in top parent's allMarkTypes */
 		top_parentrc->allMarkTypes |= childrc->allMarkTypes;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 25545029d7..13232d797a 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -215,10 +215,23 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 			 * Ignore partitioned indexes, since they are not usable for
 			 * queries.
 			 */
-			if (indexRelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+			switch ((RelKind) indexRelation->rd_rel->relkind)
 			{
-				index_close(indexRelation, NoLock);
-				continue;
+				case RELKIND_PARTITIONED_INDEX:
+					index_close(indexRelation, NoLock);
+					continue;
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 
 			/*
@@ -442,15 +455,26 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 	rel->statlist = get_relation_statistics(rel, relation);
 
 	/* Grab foreign-table info using the relcache, while we have it */
-	if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
-		rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
-	}
-	else
-	{
-		rel->serverid = InvalidOid;
-		rel->fdwroutine = NULL;
+		case RELKIND_FOREIGN_TABLE:
+			rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
+			rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			rel->serverid = InvalidOid;
+			rel->fdwroutine = NULL;
+			break;
 	}
 
 	/* Collect info about relation's foreign keys, if relevant */
@@ -460,8 +484,25 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 	 * Collect info about relation's partitioning scheme, if any. Only
 	 * inheritance parents may be partitioned.
 	 */
-	if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		set_relation_partition_info(root, rel, relation);
+	switch ((RelKind) relation->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			if (inhparent)
+				set_relation_partition_info(root, rel, relation);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	table_close(relation, NoLock);
 
@@ -955,7 +996,7 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
 	BlockNumber relallvisible;
 	double		density;
 
-	switch (rel->rd_rel->relkind)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
@@ -1063,6 +1104,11 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
 			*tuples = rel->rd_rel->reltuples;
 			*allvisfrac = 0;
 			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* else it has no disk storage; probably shouldn't get here? */
 			*pages = 0;
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 25abc544fc..011f9829a9 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -944,37 +944,59 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
 
 	relation = relation_openrv(table_like_clause->relation, AccessShareLock);
 
-	if (relation->rd_rel->relkind != RELKIND_RELATION &&
-		relation->rd_rel->relkind != RELKIND_VIEW &&
-		relation->rd_rel->relkind != RELKIND_MATVIEW &&
-		relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
-		relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-		relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
-						RelationGetRelationName(relation))));
+	switch ((RelKind) relation->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
+							RelationGetRelationName(relation))));
+			break;
+	}
 
 	cancel_parser_errposition_callback(&pcbstate);
 
 	/*
 	 * Check for privileges
 	 */
-	if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-	{
-		aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
-									 ACL_USAGE);
-		if (aclresult != ACLCHECK_OK)
-			aclcheck_error(aclresult, OBJECT_TYPE,
-						   RelationGetRelationName(relation));
-	}
-	else
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
-									  ACL_SELECT);
-		if (aclresult != ACLCHECK_OK)
-			aclcheck_error(aclresult, get_relkind_objtype(relation->rd_rel->relkind),
-						   RelationGetRelationName(relation));
+		case RELKIND_COMPOSITE_TYPE:
+			aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
+										 ACL_USAGE);
+			if (aclresult != ACLCHECK_OK)
+				aclcheck_error(aclresult, OBJECT_TYPE,
+							   RelationGetRelationName(relation));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
+										  ACL_SELECT);
+			if (aclresult != ACLCHECK_OK)
+				aclcheck_error(aclresult, get_relkind_objtype(relation->rd_rel->relkind),
+							   RelationGetRelationName(relation));
+			break;
 	}
 
 	tupleDesc = RelationGetDescr(relation);
@@ -2306,13 +2328,27 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 
 					rel = table_openrv(inh, AccessShareLock);
 					/* check user requested inheritance from valid relkind */
-					if (rel->rd_rel->relkind != RELKIND_RELATION &&
-						rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-						rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-						ereport(ERROR,
-								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-								 errmsg("inherited relation \"%s\" is not a table or foreign table",
-										inh->relname)));
+					switch ((RelKind) rel->rd_rel->relkind)
+					{
+						case RELKIND_RELATION:
+						case RELKIND_FOREIGN_TABLE:
+						case RELKIND_PARTITIONED_TABLE:
+							break;
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_SEQUENCE:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_INDEX:
+						case RELKIND_MATVIEW:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_VIEW:
+						case RELKIND_NULL:
+						default:
+							ereport(ERROR,
+									(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+									 errmsg("inherited relation \"%s\" is not a table or foreign table",
+											inh->relname)));
+							break;
+					}
 					for (count = 0; count < rel->rd_att->natts; count++)
 					{
 						Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
@@ -2448,13 +2484,27 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 
 					rel = table_openrv(inh, AccessShareLock);
 					/* check user requested inheritance from valid relkind */
-					if (rel->rd_rel->relkind != RELKIND_RELATION &&
-						rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
-						rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-						ereport(ERROR,
-								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-								 errmsg("inherited relation \"%s\" is not a table or foreign table",
-										inh->relname)));
+					switch ((RelKind) rel->rd_rel->relkind)
+					{
+						case RELKIND_RELATION:
+						case RELKIND_FOREIGN_TABLE:
+						case RELKIND_PARTITIONED_TABLE:
+							break;
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_SEQUENCE:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_INDEX:
+						case RELKIND_MATVIEW:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_VIEW:
+						case RELKIND_NULL:
+						default:
+							ereport(ERROR,
+									(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+									 errmsg("inherited relation \"%s\" is not a table or foreign table",
+											inh->relname)));
+							break;
+					}
 					for (count = 0; count < rel->rd_att->natts; count++)
 					{
 						Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
@@ -2763,10 +2813,27 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
 	 */
 	rel = table_openrv(stmt->relation, AccessExclusiveLock);
 
-	if (rel->rd_rel->relkind == RELKIND_MATVIEW)
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("rules on materialized views are not supported")));
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_MATVIEW:
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("rules on materialized views are not supported")));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
+
 
 	/* Set up pstate */
 	pstate = make_parsestate(NULL);
@@ -3097,15 +3164,26 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
 
 	/* Set up CreateStmtContext */
 	cxt.pstate = pstate;
-	if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		cxt.stmtType = "ALTER FOREIGN TABLE";
-		cxt.isforeign = true;
-	}
-	else
-	{
-		cxt.stmtType = "ALTER TABLE";
-		cxt.isforeign = false;
+		case RELKIND_FOREIGN_TABLE:
+			cxt.stmtType = "ALTER FOREIGN TABLE";
+			cxt.isforeign = true;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			cxt.stmtType = "ALTER TABLE";
+			cxt.isforeign = false;
+			break;
 	}
 	cxt.relation = stmt->relation;
 	cxt.rel = rel;
@@ -3722,7 +3800,7 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
 {
 	Relation	parentRel = cxt->rel;
 
-	switch (parentRel->rd_rel->relkind)
+	switch ((RelKind) parentRel->rd_rel->relkind)
 	{
 		case RELKIND_PARTITIONED_TABLE:
 			/* transform the partition bound, if any */
@@ -3757,6 +3835,13 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
 					 errmsg("index \"%s\" is not partitioned",
 							RelationGetRelationName(parentRel))));
 			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* parser shouldn't let this case through */
 			elog(ERROR, "\"%s\" is not a partitioned table or index",
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 7553d55987..c872ab1825 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -3137,11 +3137,26 @@ check_default_partition_contents(Relation parent, Relation default_rel,
 	 * Scan the default partition and its subpartitions, and check for rows
 	 * that do not satisfy the revised partition constraints.
 	 */
-	if (default_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		all_parts = find_all_inheritors(RelationGetRelid(default_rel),
-										AccessExclusiveLock, NULL);
-	else
-		all_parts = list_make1_oid(RelationGetRelid(default_rel));
+	switch ((RelKind) default_rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			all_parts = find_all_inheritors(RelationGetRelid(default_rel),
+											AccessExclusiveLock, NULL);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			all_parts = list_make1_oid(RelationGetRelid(default_rel));
+			break;
+	}
 
 	foreach(lc, all_parts)
 	{
@@ -3196,19 +3211,30 @@ check_default_partition_contents(Relation parent, Relation default_rel,
 		 * Only RELKIND_RELATION relations (i.e. leaf partitions) need to be
 		 * scanned.
 		 */
-		if (part_rel->rd_rel->relkind != RELKIND_RELATION)
+		switch ((RelKind) part_rel->rd_rel->relkind)
 		{
-			if (part_rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+			case RELKIND_RELATION:
+				break;
+			case RELKIND_FOREIGN_TABLE:
 				ereport(WARNING,
 						(errcode(ERRCODE_CHECK_VIOLATION),
 						 errmsg("skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
 								RelationGetRelationName(part_rel),
 								RelationGetRelationName(default_rel))));
-
-			if (RelationGetRelid(default_rel) != RelationGetRelid(part_rel))
-				table_close(part_rel, NoLock);
-
-			continue;
+				/* fallthrough */
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				if (RelationGetRelid(default_rel) != RelationGetRelid(part_rel))
+					table_close(part_rel, NoLock);
+				continue;
 		}
 
 		estate = CreateExecutorState();
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 9c7d4b0c60..9b43c68ed6 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2058,9 +2058,23 @@ do_autovacuum(void)
 		bool		doanalyze;
 		bool		wraparound;
 
-		if (classForm->relkind != RELKIND_RELATION &&
-			classForm->relkind != RELKIND_MATVIEW)
-			continue;
+		switch ((RelKind) classForm->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_MATVIEW:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				continue;
+		}
 
 		relid = classForm->oid;
 
@@ -2720,9 +2734,24 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
 	bytea	   *relopts;
 	AutoVacOpts *av;
 
-	Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
-		   ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW ||
-		   ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
+	switch ((RelKind) ((Form_pg_class) GETSTRUCT(tup))->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			Assert(false);
+			break;
+	}
 
 	relopts = extractRelOptions(tup, pg_class_desc, NULL);
 	if (relopts == NULL)
@@ -2800,17 +2829,34 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	 * main table reloptions if the toast table itself doesn't have.
 	 */
 	avopts = extract_autovac_opts(classTup, pg_class_desc);
-	if (classForm->relkind == RELKIND_TOASTVALUE &&
-		avopts == NULL && table_toast_map != NULL)
+	switch ((RelKind) classForm->relkind)
 	{
-		av_relation *hentry;
-		bool		found;
+		case RELKIND_TOASTVALUE:
+			if (avopts == NULL && table_toast_map != NULL)
+			{
+				av_relation *hentry;
+				bool		found;
 
-		hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-		if (found && hentry->ar_hasrelopts)
-			avopts = &hentry->ar_reloptions;
+				hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
+				if (found && hentry->ar_hasrelopts)
+					avopts = &hentry->ar_reloptions;
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
+
 	/* fetch the pgstat table entry */
 	tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
 										 shared, dbentry);
@@ -2820,8 +2866,24 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 							  &dovacuum, &doanalyze, &wraparound);
 
 	/* ignore ANALYZE for toast tables */
-	if (classForm->relkind == RELKIND_TOASTVALUE)
-		doanalyze = false;
+	switch ((RelKind) classForm->relkind)
+	{
+		case RELKIND_TOASTVALUE:
+			doanalyze = false;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/* OK, it needs something done */
 	if (doanalyze || dovacuum)
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 096b0fcef0..fc9321c1ae 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -414,7 +414,7 @@ perform_base_backup(basebackup_options *opt)
 			if (ti->path == NULL)
 			{
 				struct stat statbuf;
-				bool	sendtblspclinks = true;
+				bool		sendtblspclinks = true;
 
 				/* In the main tar, include the backup_label first... */
 				sendFileWithContent(BACKUP_LABEL_FILE, labelfile->data,
@@ -1777,8 +1777,8 @@ sendFile(const char *readfilename, const char *tarfilename,
 	}
 
 	/*
-	 * Pad to a block boundary, per tar format requirements. (This small
-	 * piece of data is probably not worth throttling, and is not checksummed
+	 * Pad to a block boundary, per tar format requirements. (This small piece
+	 * of data is probably not worth throttling, and is not checksummed
 	 * because it's not actually part of the file.)
 	 */
 	pad = tarPaddingBytesRequired(len);
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 642a1c767f..08310078c5 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -1643,8 +1643,23 @@ ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid,
 					 * understand, so it doesn't make sense to handle the few
 					 * cases we do.
 					 */
-					if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
-						goto change_done;
+					switch ((RelKind) relation->rd_rel->relkind)
+					{
+						case RELKIND_SEQUENCE:
+							goto change_done;
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_FOREIGN_TABLE:
+						case RELKIND_INDEX:
+						case RELKIND_MATVIEW:
+						case RELKIND_PARTITIONED_TABLE:
+						case RELKIND_RELATION:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_VIEW:
+						case RELKIND_NULL:
+						default:
+							break;
+					}
 
 					/* user-triggered change */
 					if (!IsToastRelation(relation))
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index c27d970589..f0419386d9 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -765,24 +765,38 @@ copy_table(Relation rel)
 
 	/* Start copy on the publisher. */
 	initStringInfo(&cmd);
-	if (lrel.relkind == RELKIND_RELATION)
-		appendStringInfo(&cmd, "COPY %s TO STDOUT",
-						 quote_qualified_identifier(lrel.nspname, lrel.relname));
-	else
+	switch ((RelKind) lrel.relkind)
 	{
-		/*
-		 * For non-tables, we need to do COPY (SELECT ...), but we can't just
-		 * do SELECT * because we need to not copy generated columns.
-		 */
-		appendStringInfo(&cmd, "COPY (SELECT ");
-		for (int i = 0; i < lrel.natts; i++)
-		{
-			appendStringInfoString(&cmd, quote_identifier(lrel.attnames[i]));
-			if (i < lrel.natts - 1)
-				appendStringInfoString(&cmd, ", ");
-		}
-		appendStringInfo(&cmd, " FROM %s) TO STDOUT",
-						 quote_qualified_identifier(lrel.nspname, lrel.relname));
+		case RELKIND_RELATION:
+			appendStringInfo(&cmd, "COPY %s TO STDOUT",
+							 quote_qualified_identifier(lrel.nspname, lrel.relname));
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+
+			/*
+			 * For non-tables, we need to do COPY (SELECT ...), but we can't
+			 * just do SELECT * because we need to not copy generated columns.
+			 */
+			appendStringInfo(&cmd, "COPY (SELECT ");
+			for (int i = 0; i < lrel.natts; i++)
+			{
+				appendStringInfoString(&cmd, quote_identifier(lrel.attnames[i]));
+				if (i < lrel.natts - 1)
+					appendStringInfoString(&cmd, ", ");
+			}
+			appendStringInfo(&cmd, " FROM %s) TO STDOUT",
+							 quote_qualified_identifier(lrel.nspname, lrel.relname));
+			break;
 	}
 	res = walrcv_exec(wrconn, cmd.data, 0, NULL);
 	pfree(cmd.data);
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index a752a1224d..bc047c0b1e 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -646,12 +646,27 @@ apply_handle_insert(StringInfo s)
 	MemoryContextSwitchTo(oldctx);
 
 	/* For a partitioned table, insert the tuple into a partition. */
-	if (rel->localrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		apply_handle_tuple_routing(estate->es_result_relation_info, estate,
-								   remoteslot, NULL, rel, CMD_INSERT);
-	else
-		apply_handle_insert_internal(estate->es_result_relation_info, estate,
-									 remoteslot);
+	switch ((RelKind) rel->localrel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			apply_handle_tuple_routing(estate->es_result_relation_info, estate,
+									   remoteslot, NULL, rel, CMD_INSERT);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			apply_handle_insert_internal(estate->es_result_relation_info, estate,
+										 remoteslot);
+			break;
+	}
 
 	PopActiveSnapshot();
 
@@ -781,12 +796,27 @@ apply_handle_update(StringInfo s)
 	MemoryContextSwitchTo(oldctx);
 
 	/* For a partitioned table, apply update to correct partition. */
-	if (rel->localrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		apply_handle_tuple_routing(estate->es_result_relation_info, estate,
-								   remoteslot, &newtup, rel, CMD_UPDATE);
-	else
-		apply_handle_update_internal(estate->es_result_relation_info, estate,
-									 remoteslot, &newtup, rel);
+	switch ((RelKind) rel->localrel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			apply_handle_tuple_routing(estate->es_result_relation_info, estate,
+									   remoteslot, &newtup, rel, CMD_UPDATE);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			apply_handle_update_internal(estate->es_result_relation_info, estate,
+										 remoteslot, &newtup, rel);
+			break;
+	}
 
 	PopActiveSnapshot();
 
@@ -904,12 +934,27 @@ apply_handle_delete(StringInfo s)
 	MemoryContextSwitchTo(oldctx);
 
 	/* For a partitioned table, apply delete to correct partition. */
-	if (rel->localrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		apply_handle_tuple_routing(estate->es_result_relation_info, estate,
-								   remoteslot, NULL, rel, CMD_DELETE);
-	else
-		apply_handle_delete_internal(estate->es_result_relation_info, estate,
-									 remoteslot, &rel->remoterel);
+	switch ((RelKind) rel->localrel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			apply_handle_tuple_routing(estate->es_result_relation_info, estate,
+									   remoteslot, NULL, rel, CMD_DELETE);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			apply_handle_delete_internal(estate->es_result_relation_info, estate,
+										 remoteslot, &rel->remoterel);
+			break;
+	}
 
 	PopActiveSnapshot();
 
@@ -1273,41 +1318,61 @@ apply_handle_truncate(StringInfo s)
 		 * Truncate partitions if we got a message to truncate a partitioned
 		 * table.
 		 */
-		if (rel->localrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+		switch ((RelKind) rel->localrel->rd_rel->relkind)
 		{
-			ListCell   *child;
-			List	   *children = find_all_inheritors(rel->localreloid,
-													   RowExclusiveLock,
-													   NULL);
-
-			foreach(child, children)
-			{
-				Oid			childrelid = lfirst_oid(child);
-				Relation	childrel;
-
-				if (list_member_oid(relids, childrelid))
-					continue;
-
-				/* find_all_inheritors already got lock */
-				childrel = table_open(childrelid, NoLock);
-
-				/*
-				 * Ignore temp tables of other backends.  See similar code in
-				 * ExecuteTruncate().
-				 */
-				if (RELATION_IS_OTHER_TEMP(childrel))
+			case RELKIND_PARTITIONED_TABLE:
 				{
-					table_close(childrel, RowExclusiveLock);
-					continue;
-				}
+					ListCell   *child;
+					List	   *children = find_all_inheritors(rel->localreloid,
+															   RowExclusiveLock,
+															   NULL);
 
-				rels = lappend(rels, childrel);
-				part_rels = lappend(part_rels, childrel);
-				relids = lappend_oid(relids, childrelid);
-				/* Log this relation only if needed for logical decoding */
-				if (RelationIsLogicallyLogged(childrel))
-					relids_logged = lappend_oid(relids_logged, childrelid);
-			}
+					foreach(child, children)
+					{
+						Oid			childrelid = lfirst_oid(child);
+						Relation	childrel;
+
+						if (list_member_oid(relids, childrelid))
+							continue;
+
+						/* find_all_inheritors already got lock */
+						childrel = table_open(childrelid, NoLock);
+
+						/*
+						 * Ignore temp tables of other backends.  See similar
+						 * code in ExecuteTruncate().
+						 */
+						if (RELATION_IS_OTHER_TEMP(childrel))
+						{
+							table_close(childrel, RowExclusiveLock);
+							continue;
+						}
+
+						rels = lappend(rels, childrel);
+						part_rels = lappend(part_rels, childrel);
+						relids = lappend_oid(relids, childrelid);
+
+						/*
+						 * Log this relation only if needed for logical
+						 * decoding
+						 */
+						if (RelationIsLogicallyLogged(childrel))
+							relids_logged = lappend_oid(relids_logged, childrelid);
+					}
+				}
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 	}
 
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 57bbb6288c..54ae4af52b 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -100,8 +100,8 @@ int			max_replication_slots = 0;	/* the maximum number of replication
 										 * slots */
 
 static ReplicationSlot *SearchNamedReplicationSlot(const char *name);
-static int ReplicationSlotAcquireInternal(ReplicationSlot *slot,
-										  const char *name, SlotAcquireBehavior behavior);
+static int	ReplicationSlotAcquireInternal(ReplicationSlot *slot,
+										   const char *name, SlotAcquireBehavior behavior);
 static void ReplicationSlotDropAcquired(void);
 static void ReplicationSlotDropPtr(ReplicationSlot *slot);
 
@@ -335,7 +335,7 @@ static ReplicationSlot *
 SearchNamedReplicationSlot(const char *name)
 {
 	int			i;
-	ReplicationSlot	*slot = NULL;
+	ReplicationSlot *slot = NULL;
 
 	Assert(LWLockHeldByMeInMode(ReplicationSlotControlLock,
 								LW_SHARED));
@@ -434,8 +434,8 @@ retry:
 
 	/*
 	 * If we found the slot but it's already active in another process, we
-	 * either error out, return the PID of the owning process, or retry
-	 * after a short wait, as caller specified.
+	 * either error out, return the PID of the owning process, or retry after
+	 * a short wait, as caller specified.
 	 */
 	if (active_pid != MyProcPid)
 	{
@@ -454,7 +454,7 @@ retry:
 		goto retry;
 	}
 	else if (behavior == SAB_Block)
-		ConditionVariableCancelSleep();	/* no sleep needed after all */
+		ConditionVariableCancelSleep(); /* no sleep needed after all */
 
 	/* Let everybody know we've modified this slot */
 	ConditionVariableBroadcast(&s->active_cv);
@@ -1143,8 +1143,8 @@ restart:
 		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
 		XLogRecPtr	restart_lsn = InvalidXLogRecPtr;
 		NameData	slotname;
-		int		wspid;
-		int		last_signaled_pid = 0;
+		int			wspid;
+		int			last_signaled_pid = 0;
 
 		if (!s->in_use)
 			continue;
@@ -1167,20 +1167,20 @@ restart:
 			/*
 			 * Try to mark this slot as used by this process.
 			 *
-			 * Note that ReplicationSlotAcquireInternal(SAB_Inquire)
-			 * should not cancel the prepared condition variable
-			 * if this slot is active in other process. Because in this case
-			 * we have to wait on that CV for the process owning
-			 * the slot to be terminated, later.
+			 * Note that ReplicationSlotAcquireInternal(SAB_Inquire) should
+			 * not cancel the prepared condition variable if this slot is
+			 * active in other process. Because in this case we have to wait
+			 * on that CV for the process owning the slot to be terminated,
+			 * later.
 			 */
 			wspid = ReplicationSlotAcquireInternal(s, NULL, SAB_Inquire);
 
 			/*
-			 * Exit the loop if we successfully acquired the slot or
-			 * the slot was dropped during waiting for the owning process
-			 * to be terminated. For example, the latter case is likely to
-			 * happen when the slot is temporary because it's automatically
-			 * dropped by the termination of the owning process.
+			 * Exit the loop if we successfully acquired the slot or the slot
+			 * was dropped during waiting for the owning process to be
+			 * terminated. For example, the latter case is likely to happen
+			 * when the slot is temporary because it's automatically dropped
+			 * by the termination of the owning process.
 			 */
 			if (wspid <= 0)
 				break;
@@ -1188,13 +1188,13 @@ restart:
 			/*
 			 * Signal to terminate the process that owns the slot.
 			 *
-			 * There is the race condition where other process may own
-			 * the slot after the process using it was terminated and before
-			 * this process owns it. To handle this case, we signal again
-			 * if the PID of the owning process is changed than the last.
+			 * There is the race condition where other process may own the
+			 * slot after the process using it was terminated and before this
+			 * process owns it. To handle this case, we signal again if the
+			 * PID of the owning process is changed than the last.
 			 *
-			 * XXX This logic assumes that the same PID is not reused
-			 * very quickly.
+			 * XXX This logic assumes that the same PID is not reused very
+			 * quickly.
 			 */
 			if (last_signaled_pid != wspid)
 			{
@@ -1211,8 +1211,8 @@ restart:
 		ConditionVariableCancelSleep();
 
 		/*
-		 * Do nothing here and start from scratch if the slot has
-		 * already been dropped.
+		 * Do nothing here and start from scratch if the slot has already been
+		 * dropped.
 		 */
 		if (wspid == -1)
 			goto restart;
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 9989df1107..93cde08936 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -262,14 +262,27 @@ DefineQueryRewrite(const char *rulename,
 	 * Internal callers can target materialized views, but transformRuleStmt()
 	 * blocks them for users.  Don't mention them in the error message.
 	 */
-	if (event_relation->rd_rel->relkind != RELKIND_RELATION &&
-		event_relation->rd_rel->relkind != RELKIND_MATVIEW &&
-		event_relation->rd_rel->relkind != RELKIND_VIEW &&
-		event_relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table or view",
-						RelationGetRelationName(event_relation))));
+	switch ((RelKind) event_relation->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table or view",
+							RelationGetRelationName(event_relation))));
+			break;
+	}
 
 	if (!allowSystemTableMods && IsSystemRelation(event_relation))
 		ereport(ERROR,
@@ -421,69 +434,83 @@ DefineQueryRewrite(const char *rulename,
 		 * views is just a kluge to allow dump/reload of views that
 		 * participate in circular dependencies.)
 		 */
-		if (event_relation->rd_rel->relkind != RELKIND_VIEW &&
-			event_relation->rd_rel->relkind != RELKIND_MATVIEW)
+		switch ((RelKind) event_relation->rd_rel->relkind)
 		{
-			TableScanDesc scanDesc;
-			Snapshot	snapshot;
-			TupleTableSlot *slot;
-
-			if (event_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+			case RELKIND_VIEW:
+			case RELKIND_MATVIEW:
+				break;
+			case RELKIND_PARTITIONED_TABLE:
 				ereport(ERROR,
 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 						 errmsg("cannot convert partitioned table \"%s\" to a view",
 								RelationGetRelationName(event_relation))));
-
-			if (event_relation->rd_rel->relispartition)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("cannot convert partition \"%s\" to a view",
-								RelationGetRelationName(event_relation))));
-
-			snapshot = RegisterSnapshot(GetLatestSnapshot());
-			scanDesc = table_beginscan(event_relation, snapshot, 0, NULL);
-			slot = table_slot_create(event_relation, NULL);
-			if (table_scan_getnextslot(scanDesc, ForwardScanDirection, slot))
-				ereport(ERROR,
-						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("could not convert table \"%s\" to a view because it is not empty",
-								RelationGetRelationName(event_relation))));
-			ExecDropSingleTupleTableSlot(slot);
-			table_endscan(scanDesc);
-			UnregisterSnapshot(snapshot);
-
-			if (event_relation->rd_rel->relhastriggers)
-				ereport(ERROR,
-						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("could not convert table \"%s\" to a view because it has triggers",
-								RelationGetRelationName(event_relation)),
-						 errhint("In particular, the table cannot be involved in any foreign key relationships.")));
-
-			if (event_relation->rd_rel->relhasindex)
-				ereport(ERROR,
-						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("could not convert table \"%s\" to a view because it has indexes",
-								RelationGetRelationName(event_relation))));
-
-			if (event_relation->rd_rel->relhassubclass)
-				ereport(ERROR,
-						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("could not convert table \"%s\" to a view because it has child tables",
-								RelationGetRelationName(event_relation))));
-
-			if (event_relation->rd_rel->relrowsecurity)
-				ereport(ERROR,
-						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("could not convert table \"%s\" to a view because it has row security enabled",
-								RelationGetRelationName(event_relation))));
-
-			if (relation_has_policies(event_relation))
-				ereport(ERROR,
-						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("could not convert table \"%s\" to a view because it has row security policies",
-								RelationGetRelationName(event_relation))));
-
-			RelisBecomingView = true;
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				{
+					TableScanDesc scanDesc;
+					Snapshot	snapshot;
+					TupleTableSlot *slot;
+
+					if (event_relation->rd_rel->relispartition)
+						ereport(ERROR,
+								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+								 errmsg("cannot convert partition \"%s\" to a view",
+										RelationGetRelationName(event_relation))));
+
+					snapshot = RegisterSnapshot(GetLatestSnapshot());
+					scanDesc = table_beginscan(event_relation, snapshot, 0, NULL);
+					slot = table_slot_create(event_relation, NULL);
+					if (table_scan_getnextslot(scanDesc, ForwardScanDirection, slot))
+						ereport(ERROR,
+								(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+								 errmsg("could not convert table \"%s\" to a view because it is not empty",
+										RelationGetRelationName(event_relation))));
+					ExecDropSingleTupleTableSlot(slot);
+					table_endscan(scanDesc);
+					UnregisterSnapshot(snapshot);
+
+					if (event_relation->rd_rel->relhastriggers)
+						ereport(ERROR,
+								(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+								 errmsg("could not convert table \"%s\" to a view because it has triggers",
+										RelationGetRelationName(event_relation)),
+								 errhint("In particular, the table cannot be involved in any foreign key relationships.")));
+
+					if (event_relation->rd_rel->relhasindex)
+						ereport(ERROR,
+								(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+								 errmsg("could not convert table \"%s\" to a view because it has indexes",
+										RelationGetRelationName(event_relation))));
+
+					if (event_relation->rd_rel->relhassubclass)
+						ereport(ERROR,
+								(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+								 errmsg("could not convert table \"%s\" to a view because it has child tables",
+										RelationGetRelationName(event_relation))));
+
+					if (event_relation->rd_rel->relrowsecurity)
+						ereport(ERROR,
+								(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+								 errmsg("could not convert table \"%s\" to a view because it has row security enabled",
+										RelationGetRelationName(event_relation))));
+
+					if (relation_has_policies(event_relation))
+						ereport(ERROR,
+								(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+								 errmsg("could not convert table \"%s\" to a view because it has row security policies",
+										RelationGetRelationName(event_relation))));
+
+					RelisBecomingView = true;
+				}
+				break;
 		}
 	}
 	else
@@ -920,12 +947,26 @@ RangeVarCallbackForRenameRule(const RangeVar *rv, Oid relid, Oid oldrelid,
 	form = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* only tables and views can have rules */
-	if (form->relkind != RELKIND_RELATION &&
-		form->relkind != RELKIND_VIEW &&
-		form->relkind != RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a table or view", rv->relname)));
+	switch ((RelKind) form->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("\"%s\" is not a table or view", rv->relname)));
+			break;
+	}
 
 	if (!allowSystemTableMods && IsSystemClass(relid, form))
 		ereport(ERROR,
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index fe777c3103..76c0b40b79 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -902,25 +902,42 @@ rewriteTargetListIU(List *targetList,
 		 * For an UPDATE on a trigger-updatable view, provide a dummy entry
 		 * whenever there is no explicit assignment.
 		 */
-		if (new_tle == NULL && commandType == CMD_UPDATE &&
-			target_relation->rd_rel->relkind == RELKIND_VIEW &&
-			view_has_instead_trigger(target_relation, CMD_UPDATE))
+		switch ((RelKind) target_relation->rd_rel->relkind)
 		{
-			Node	   *new_expr;
-
-			new_expr = (Node *) makeVar(result_rti,
-										attrno,
-										att_tup->atttypid,
-										att_tup->atttypmod,
-										att_tup->attcollation,
-										0);
+			case RELKIND_VIEW:
+				if (new_tle == NULL && commandType == CMD_UPDATE &&
+					view_has_instead_trigger(target_relation, CMD_UPDATE))
+				{
+					Node	   *new_expr;
 
-			new_tle = makeTargetEntry((Expr *) new_expr,
-									  attrno,
-									  pstrdup(NameStr(att_tup->attname)),
-									  false);
+					new_expr = (Node *) makeVar(result_rti,
+												attrno,
+												att_tup->atttypid,
+												att_tup->atttypmod,
+												att_tup->attcollation,
+												0);
+
+					new_tle = makeTargetEntry((Expr *) new_expr,
+											  attrno,
+											  pstrdup(NameStr(att_tup->attname)),
+											  false);
+				}
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
+
 		if (new_tle)
 			new_tlist = lappend(new_tlist, new_tle);
 	}
@@ -1316,39 +1333,54 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
 	 * skip this check in that case --- it isn't an auto-updatable view.
 	 */
 	isAutoUpdatableView = false;
-	if (!force_nulls &&
-		target_relation->rd_rel->relkind == RELKIND_VIEW &&
-		!view_has_instead_trigger(target_relation, CMD_INSERT))
+	switch ((RelKind) target_relation->rd_rel->relkind)
 	{
-		List	   *locks;
-		bool		hasUpdate;
-		bool		found;
-		ListCell   *l;
+		case RELKIND_VIEW:
+			if (!force_nulls && !view_has_instead_trigger(target_relation, CMD_INSERT))
+			{
+				List	   *locks;
+				bool		hasUpdate;
+				bool		found;
+				ListCell   *l;
 
-		/* Look for an unconditional DO INSTEAD rule */
-		locks = matchLocks(CMD_INSERT, target_relation->rd_rules,
-						   parsetree->resultRelation, parsetree, &hasUpdate);
+				/* Look for an unconditional DO INSTEAD rule */
+				locks = matchLocks(CMD_INSERT, target_relation->rd_rules,
+								   parsetree->resultRelation, parsetree, &hasUpdate);
 
-		found = false;
-		foreach(l, locks)
-		{
-			RewriteRule *rule_lock = (RewriteRule *) lfirst(l);
+				found = false;
+				foreach(l, locks)
+				{
+					RewriteRule *rule_lock = (RewriteRule *) lfirst(l);
 
-			if (rule_lock->isInstead &&
-				rule_lock->qual == NULL)
-			{
-				found = true;
-				break;
-			}
-		}
+					if (rule_lock->isInstead &&
+						rule_lock->qual == NULL)
+					{
+						found = true;
+						break;
+					}
+				}
 
-		/*
-		 * If we didn't find an unconditional DO INSTEAD rule, assume that the
-		 * view is auto-updatable.  If it isn't, rewriteTargetView() will
-		 * throw an error.
-		 */
-		if (!found)
-			isAutoUpdatableView = true;
+				/*
+				 * If we didn't find an unconditional DO INSTEAD rule, assume
+				 * that the view is auto-updatable.  If it isn't,
+				 * rewriteTargetView() will throw an error.
+				 */
+				if (!found)
+					isAutoUpdatableView = true;
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	newValues = NIL;
@@ -1450,55 +1482,72 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
 	const char *attrname;
 	TargetEntry *tle;
 
-	if (target_relation->rd_rel->relkind == RELKIND_RELATION ||
-		target_relation->rd_rel->relkind == RELKIND_MATVIEW ||
-		target_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-	{
-		/*
-		 * Emit CTID so that executor can find the row to update or delete.
-		 */
-		var = makeVar(parsetree->resultRelation,
-					  SelfItemPointerAttributeNumber,
-					  TIDOID,
-					  -1,
-					  InvalidOid,
-					  0);
-
-		attrname = "ctid";
-	}
-	else if (target_relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+	switch ((RelKind) target_relation->rd_rel->relkind)
 	{
-		/*
-		 * Let the foreign table's FDW add whatever junk TLEs it wants.
-		 */
-		FdwRoutine *fdwroutine;
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				/*
+				 * Emit CTID so that executor can find the row to update or
+				 * delete.
+				 */
+				var = makeVar(parsetree->resultRelation,
+							  SelfItemPointerAttributeNumber,
+							  TIDOID,
+							  -1,
+							  InvalidOid,
+							  0);
+
+				attrname = "ctid";
+			}
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			{
+				/*
+				 * Let the foreign table's FDW add whatever junk TLEs it
+				 * wants.
+				 */
+				FdwRoutine *fdwroutine;
 
-		fdwroutine = GetFdwRoutineForRelation(target_relation, false);
+				fdwroutine = GetFdwRoutineForRelation(target_relation, false);
 
-		if (fdwroutine->AddForeignUpdateTargets != NULL)
-			fdwroutine->AddForeignUpdateTargets(parsetree, target_rte,
-												target_relation);
+				if (fdwroutine->AddForeignUpdateTargets != NULL)
+					fdwroutine->AddForeignUpdateTargets(parsetree, target_rte,
+														target_relation);
 
-		/*
-		 * If we have a row-level trigger corresponding to the operation, emit
-		 * a whole-row Var so that executor will have the "old" row to pass to
-		 * the trigger.  Alas, this misses system columns.
-		 */
-		if (target_relation->trigdesc &&
-			((parsetree->commandType == CMD_UPDATE &&
-			  (target_relation->trigdesc->trig_update_after_row ||
-			   target_relation->trigdesc->trig_update_before_row)) ||
-			 (parsetree->commandType == CMD_DELETE &&
-			  (target_relation->trigdesc->trig_delete_after_row ||
-			   target_relation->trigdesc->trig_delete_before_row))))
-		{
-			var = makeWholeRowVar(target_rte,
-								  parsetree->resultRelation,
-								  0,
-								  false);
+				/*
+				 * If we have a row-level trigger corresponding to the
+				 * operation, emit a whole-row Var so that executor will have
+				 * the "old" row to pass to the trigger.  Alas, this misses
+				 * system columns.
+				 */
+				if (target_relation->trigdesc &&
+					((parsetree->commandType == CMD_UPDATE &&
+					  (target_relation->trigdesc->trig_update_after_row ||
+					   target_relation->trigdesc->trig_update_before_row)) ||
+					 (parsetree->commandType == CMD_DELETE &&
+					  (target_relation->trigdesc->trig_delete_after_row ||
+					   target_relation->trigdesc->trig_delete_before_row))))
+				{
+					var = makeWholeRowVar(target_rte,
+										  parsetree->resultRelation,
+										  0,
+										  false);
 
-			attrname = "wholerow";
-		}
+					attrname = "wholerow";
+				}
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	if (var != NULL)
@@ -1909,8 +1958,23 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
 		 * In that case this test would need to be postponed till after we've
 		 * opened the rel, so that we could check its state.
 		 */
-		if (rte->relkind == RELKIND_MATVIEW)
-			continue;
+		switch ((RelKind) rte->relkind)
+		{
+			case RELKIND_MATVIEW:
+				continue;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		/*
 		 * In INSERT ... ON CONFLICT, ignore the EXCLUDED pseudo-relation;
@@ -2032,10 +2096,25 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
 		++rt_index;
 
 		/* Only normal relations can have RLS policies */
-		if (rte->rtekind != RTE_RELATION ||
-			(rte->relkind != RELKIND_RELATION &&
-			 rte->relkind != RELKIND_PARTITIONED_TABLE))
+		if (rte->rtekind != RTE_RELATION)
 			continue;
+		switch ((RelKind) rte->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				continue;
+		}
 
 		rel = table_open(rte->relid, NoLock);
 
@@ -2498,12 +2577,25 @@ view_query_is_auto_updatable(Query *viewquery, bool check_cols)
 		return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
 
 	base_rte = rt_fetch(rtr->rtindex, viewquery->rtable);
-	if (base_rte->rtekind != RTE_RELATION ||
-		(base_rte->relkind != RELKIND_RELATION &&
-		 base_rte->relkind != RELKIND_FOREIGN_TABLE &&
-		 base_rte->relkind != RELKIND_VIEW &&
-		 base_rte->relkind != RELKIND_PARTITIONED_TABLE))
-		return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
+	switch ((RelKind) base_rte->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_PARTITIONED_TABLE:
+			if (base_rte->rtekind == RTE_RELATION)
+				break;
+			/* fallthrough */
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
+	}
 
 	if (base_rte->tablesample)
 		return gettext_noop("Views containing TABLESAMPLE are not automatically updatable.");
@@ -2677,11 +2769,23 @@ relation_is_updatable(Oid reloid,
 	}
 
 	/* If the relation is a table, it is always updatable */
-	if (rel->rd_rel->relkind == RELKIND_RELATION ||
-		rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		relation_close(rel, AccessShareLock);
-		return ALL_EVENTS;
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			relation_close(rel, AccessShareLock);
+			return ALL_EVENTS;
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* Look for unconditional DO INSTEAD rules, and note supported events */
@@ -2730,84 +2834,103 @@ relation_is_updatable(Oid reloid,
 		}
 	}
 
-	/* If this is a foreign table, check which update events it supports */
-	if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+	switch ((RelKind) rel->rd_rel->relkind)
 	{
-		FdwRoutine *fdwroutine = GetFdwRoutineForRelation(rel, false);
-
-		if (fdwroutine->IsForeignRelUpdatable != NULL)
-			events |= fdwroutine->IsForeignRelUpdatable(rel);
-		else
-		{
-			/* Assume presence of executor functions is sufficient */
-			if (fdwroutine->ExecForeignInsert != NULL)
-				events |= (1 << CMD_INSERT);
-			if (fdwroutine->ExecForeignUpdate != NULL)
-				events |= (1 << CMD_UPDATE);
-			if (fdwroutine->ExecForeignDelete != NULL)
-				events |= (1 << CMD_DELETE);
-		}
+			/*
+			 * If this is a foreign table, check which update events it
+			 * supports
+			 */
+		case RELKIND_FOREIGN_TABLE:
+			{
+				FdwRoutine *fdwroutine = GetFdwRoutineForRelation(rel, false);
 
-		relation_close(rel, AccessShareLock);
-		return events;
-	}
+				if (fdwroutine->IsForeignRelUpdatable != NULL)
+					events |= fdwroutine->IsForeignRelUpdatable(rel);
+				else
+				{
+					/* Assume presence of executor functions is sufficient */
+					if (fdwroutine->ExecForeignInsert != NULL)
+						events |= (1 << CMD_INSERT);
+					if (fdwroutine->ExecForeignUpdate != NULL)
+						events |= (1 << CMD_UPDATE);
+					if (fdwroutine->ExecForeignDelete != NULL)
+						events |= (1 << CMD_DELETE);
+				}
 
-	/* Check if this is an automatically updatable view */
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-	{
-		Query	   *viewquery = get_view_query(rel);
+				relation_close(rel, AccessShareLock);
+				return events;
+			}
+			break;
+			/* Check if this is an automatically updatable view */
+		case RELKIND_VIEW:
+			{
+				Query	   *viewquery = get_view_query(rel);
 
-		if (view_query_is_auto_updatable(viewquery, false) == NULL)
-		{
-			Bitmapset  *updatable_cols;
-			int			auto_events;
-			RangeTblRef *rtr;
-			RangeTblEntry *base_rte;
-			Oid			baseoid;
+				if (view_query_is_auto_updatable(viewquery, false) == NULL)
+				{
+					Bitmapset  *updatable_cols;
+					int			auto_events;
+					RangeTblRef *rtr;
+					RangeTblEntry *base_rte;
+					Oid			baseoid;
 
-			/*
-			 * Determine which of the view's columns are updatable. If there
-			 * are none within the set of columns we are looking at, then the
-			 * view doesn't support INSERT/UPDATE, but it may still support
-			 * DELETE.
-			 */
-			view_cols_are_auto_updatable(viewquery, NULL,
-										 &updatable_cols, NULL);
+					/*
+					 * Determine which of the view's columns are updatable. If
+					 * there are none within the set of columns we are looking
+					 * at, then the view doesn't support INSERT/UPDATE, but it
+					 * may still support DELETE.
+					 */
+					view_cols_are_auto_updatable(viewquery, NULL,
+												 &updatable_cols, NULL);
 
-			if (include_cols != NULL)
-				updatable_cols = bms_int_members(updatable_cols, include_cols);
+					if (include_cols != NULL)
+						updatable_cols = bms_int_members(updatable_cols, include_cols);
 
-			if (bms_is_empty(updatable_cols))
-				auto_events = (1 << CMD_DELETE);	/* May support DELETE */
-			else
-				auto_events = ALL_EVENTS;	/* May support all events */
+					if (bms_is_empty(updatable_cols))
+						auto_events = (1 << CMD_DELETE);	/* May support DELETE */
+					else
+						auto_events = ALL_EVENTS;	/* May support all events */
 
-			/*
-			 * The base relation must also support these update commands.
-			 * Tables are always updatable, but for any other kind of base
-			 * relation we must do a recursive check limited to the columns
-			 * referenced by the locally updatable columns in this view.
-			 */
-			rtr = (RangeTblRef *) linitial(viewquery->jointree->fromlist);
-			base_rte = rt_fetch(rtr->rtindex, viewquery->rtable);
-			Assert(base_rte->rtekind == RTE_RELATION);
+					/*
+					 * The base relation must also support these update
+					 * commands. Tables are always updatable, but for any
+					 * other kind of base relation we must do a recursive
+					 * check limited to the columns referenced by the locally
+					 * updatable columns in this view.
+					 */
+					rtr = (RangeTblRef *) linitial(viewquery->jointree->fromlist);
+					base_rte = rt_fetch(rtr->rtindex, viewquery->rtable);
+					Assert(base_rte->rtekind == RTE_RELATION);
 
-			if (base_rte->relkind != RELKIND_RELATION &&
-				base_rte->relkind != RELKIND_PARTITIONED_TABLE)
-			{
-				baseoid = base_rte->relid;
-				outer_reloids = lappend_oid(outer_reloids,
-											RelationGetRelid(rel));
-				include_cols = adjust_view_column_set(updatable_cols,
-													  viewquery->targetList);
-				auto_events &= relation_is_updatable(baseoid,
-													 outer_reloids,
-													 include_triggers,
-													 include_cols);
-				outer_reloids = list_delete_last(outer_reloids);
+					if (base_rte->relkind != RELKIND_RELATION &&
+						base_rte->relkind != RELKIND_PARTITIONED_TABLE)
+					{
+						baseoid = base_rte->relid;
+						outer_reloids = lappend_oid(outer_reloids,
+													RelationGetRelid(rel));
+						include_cols = adjust_view_column_set(updatable_cols,
+															  viewquery->targetList);
+						auto_events &= relation_is_updatable(baseoid,
+															 outer_reloids,
+															 include_triggers,
+															 include_cols);
+						outer_reloids = list_delete_last(outer_reloids);
+					}
+					events |= auto_events;
+				}
 			}
-			events |= auto_events;
-		}
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* If we reach here, the relation may support some update commands */
diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c
index 0fe2f9ca83..2002cf9a20 100644
--- a/src/backend/rewrite/rowsecurity.c
+++ b/src/backend/rewrite/rowsecurity.c
@@ -123,9 +123,23 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
 	*hasSubLinks = false;
 
 	/* If this is not a normal relation, just return immediately */
-	if (rte->relkind != RELKIND_RELATION &&
-		rte->relkind != RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) rte->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return;
+	}
 
 	/* Switch to checkAsUser if it's set */
 	user_id = rte->checkAsUser ? rte->checkAsUser : GetUserId();
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 29c920800a..6eb28a2210 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2819,7 +2819,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln)
 BlockNumber
 RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
 {
-	switch (relation->rd_rel->relkind)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
 		case RELKIND_SEQUENCE:
 		case RELKIND_INDEX:
@@ -2846,12 +2846,17 @@ RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
 				return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
 			}
 		case RELKIND_VIEW:
+			elog(FATAL, "RELKIND_VIEW in RelationGetNumberOfBlocksInFork");
 		case RELKIND_COMPOSITE_TYPE:
+			elog(FATAL, "RELKIND_COMPOSITE_TYPE in RelationGetNumberOfBlocksInFork");
 		case RELKIND_FOREIGN_TABLE:
+			elog(FATAL, "RELKIND_FOREIGN_TABLE in RelationGetNumberOfBlocksInFork");
 		case RELKIND_PARTITIONED_TABLE:
+			elog(FATAL, "RELKIND_PARTITIONED_TABLE in RelationGetNumberOfBlocksInFork");
+		case RELKIND_NULL:
 		default:
-			Assert(false);
-			break;
+			elog(FATAL, "Unexpected relkind %d in RelationGetNumberOfBlocksInFork",
+				 (int) relation->rd_rel->relkind);
 	}
 
 	return 0;					/* keep compiler quiet */
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index e57fcd2538..615670ff41 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1236,8 +1236,8 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
 	/*
 	 * Set timer so we can wake up after awhile and check for a deadlock. If a
 	 * deadlock is detected, the handler sets MyProc->waitStatus =
-	 * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure rather
-	 * than success.
+	 * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
+	 * rather than success.
 	 *
 	 * By delaying the check until we've waited for a bit, we can avoid
 	 * running the rather expensive deadlock-check code in most cases.
@@ -1302,9 +1302,9 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
 		}
 
 		/*
-		 * waitStatus could change from PROC_WAIT_STATUS_WAITING to something else
-		 * asynchronously.  Read it just once per loop to prevent surprising
-		 * behavior (such as missing log messages).
+		 * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
+		 * else asynchronously.  Read it just once per loop to prevent
+		 * surprising behavior (such as missing log messages).
 		 */
 		myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
 
@@ -1504,11 +1504,12 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
 
 				/*
 				 * Currently, the deadlock checker always kicks its own
-				 * process, which means that we'll only see PROC_WAIT_STATUS_ERROR when
-				 * deadlock_state == DS_HARD_DEADLOCK, and there's no need to
-				 * print redundant messages.  But for completeness and
-				 * future-proofing, print a message if it looks like someone
-				 * else kicked us off the lock.
+				 * process, which means that we'll only see
+				 * PROC_WAIT_STATUS_ERROR when deadlock_state ==
+				 * DS_HARD_DEADLOCK, and there's no need to print redundant
+				 * messages.  But for completeness and future-proofing, print
+				 * a message if it looks like someone else kicked us off the
+				 * lock.
 				 */
 				if (deadlock_state != DS_HARD_DEADLOCK)
 					ereport(LOG,
@@ -1737,9 +1738,9 @@ CheckDeadLock(void)
 		 * preserve the flexibility to kill some other transaction than the
 		 * one detecting the deadlock.)
 		 *
-		 * RemoveFromWaitQueue sets MyProc->waitStatus to PROC_WAIT_STATUS_ERROR, so
-		 * ProcSleep will report an error after we return from the signal
-		 * handler.
+		 * RemoveFromWaitQueue sets MyProc->waitStatus to
+		 * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
+		 * return from the signal handler.
 		 */
 		Assert(MyProc->waitLock != NULL);
 		RemoveFromWaitQueue(MyProc, LockTagHashCode(&(MyProc->waitLock->tag)));
diff --git a/src/backend/storage/lmgr/spin.c b/src/backend/storage/lmgr/spin.c
index 9f7eae9339..6d76b95c27 100644
--- a/src/backend/storage/lmgr/spin.c
+++ b/src/backend/storage/lmgr/spin.c
@@ -37,7 +37,7 @@
 #define NUM_EMULATION_SEMAPHORES (NUM_SPINLOCK_SEMAPHORES + NUM_ATOMICS_SEMAPHORES)
 #else
 #define NUM_EMULATION_SEMAPHORES (NUM_SPINLOCK_SEMAPHORES)
-#endif /* DISABLE_ATOMICS */
+#endif							/* DISABLE_ATOMICS */
 
 PGSemaphore *SpinlockSemaArray;
 
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 9b0c376c8c..538d237258 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1436,34 +1436,62 @@ ProcessUtilitySlow(ParseState *pstate,
 					 * partitions are something we can put an index on, to
 					 * avoid building some indexes only to fail later.
 					 */
-					if (stmt->relation->inh &&
-						get_rel_relkind(relid) == RELKIND_PARTITIONED_TABLE)
+					switch ((RelKind) get_rel_relkind(relid))
 					{
-						ListCell   *lc;
-						List	   *inheritors = NIL;
-
-						inheritors = find_all_inheritors(relid, lockmode, NULL);
-						foreach(lc, inheritors)
-						{
-							char		relkind = get_rel_relkind(lfirst_oid(lc));
-
-							if (relkind != RELKIND_RELATION &&
-								relkind != RELKIND_MATVIEW &&
-								relkind != RELKIND_PARTITIONED_TABLE &&
-								relkind != RELKIND_FOREIGN_TABLE)
-								elog(ERROR, "unexpected relkind \"%c\" on partition \"%s\"",
-									 relkind, stmt->relation->relname);
-
-							if (relkind == RELKIND_FOREIGN_TABLE &&
-								(stmt->unique || stmt->primary))
-								ereport(ERROR,
-										(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-										 errmsg("cannot create unique index on partitioned table \"%s\"",
-												stmt->relation->relname),
-										 errdetail("Table \"%s\" contains partitions that are foreign tables.",
-												   stmt->relation->relname)));
-						}
-						list_free(inheritors);
+						case RELKIND_PARTITIONED_TABLE:
+							if (stmt->relation->inh)
+							{
+								ListCell   *lc;
+								List	   *inheritors = NIL;
+
+								inheritors = find_all_inheritors(relid, lockmode, NULL);
+								foreach(lc, inheritors)
+								{
+									char		relkind = get_rel_relkind(lfirst_oid(lc));
+
+									switch ((RelKind) relkind)
+									{
+										case RELKIND_RELATION:
+										case RELKIND_MATVIEW:
+										case RELKIND_PARTITIONED_TABLE:
+											break;
+										case RELKIND_FOREIGN_TABLE:
+											if (stmt->unique || stmt->primary)
+												ereport(ERROR,
+														(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+														 errmsg("cannot create unique index on partitioned table \"%s\"",
+																stmt->relation->relname),
+														 errdetail("Table \"%s\" contains partitions that are foreign tables.",
+																   stmt->relation->relname)));
+											break;
+										case RELKIND_NULL:
+										case RELKIND_PARTITIONED_INDEX:
+										case RELKIND_SEQUENCE:
+										case RELKIND_COMPOSITE_TYPE:
+										case RELKIND_INDEX:
+										case RELKIND_TOASTVALUE:
+										case RELKIND_VIEW:
+											elog(ERROR, "unexpected relkind \"%c\" on partition \"%s\"",
+												 relkind, stmt->relation->relname);
+											break;
+									}
+
+								}
+								list_free(inheritors);
+							}
+							break;
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_SEQUENCE:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_FOREIGN_TABLE:
+						case RELKIND_INDEX:
+						case RELKIND_MATVIEW:
+						case RELKIND_RELATION:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_VIEW:
+						case RELKIND_NULL:
+						default:
+							break;
 					}
 
 					/* Run parse analysis ... */
diff --git a/src/backend/utils/adt/amutils.c b/src/backend/utils/adt/amutils.c
index 220cd8fc52..92fd125649 100644
--- a/src/backend/utils/adt/amutils.c
+++ b/src/backend/utils/adt/amutils.c
@@ -175,11 +175,24 @@ indexam_property(FunctionCallInfo fcinfo,
 		if (!HeapTupleIsValid(tuple))
 			PG_RETURN_NULL();
 		rd_rel = (Form_pg_class) GETSTRUCT(tuple);
-		if (rd_rel->relkind != RELKIND_INDEX &&
-			rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+		switch ((RelKind) rd_rel->relkind)
 		{
-			ReleaseSysCache(tuple);
-			PG_RETURN_NULL();
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+				break;
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				ReleaseSysCache(tuple);
+				PG_RETURN_NULL();
+				break;
 		}
 		amoid = rd_rel->relam;
 		natts = rd_rel->relnatts;
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 2320c06a9b..9fe10a2f22 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -878,7 +878,7 @@ pg_relation_filenode(PG_FUNCTION_ARGS)
 	{
 		if (relform->relfilenode)
 			result = relform->relfilenode;
-		else				/* Consult the relation mapper */
+		else					/* Consult the relation mapper */
 			result = RelationMapOidToFilenode(relid,
 											  relform->relisshared);
 	}
@@ -957,17 +957,17 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
 			rnode.dbNode = MyDatabaseId;
 		if (relform->relfilenode)
 			rnode.relNode = relform->relfilenode;
-		else				/* Consult the relation mapper */
+		else					/* Consult the relation mapper */
 			rnode.relNode = RelationMapOidToFilenode(relid,
 													 relform->relisshared);
 	}
 	else
 	{
-			/* no storage, return NULL */
-			rnode.relNode = InvalidOid;
-			/* some compilers generate warnings without these next two lines */
-			rnode.dbNode = InvalidOid;
-			rnode.spcNode = InvalidOid;
+		/* no storage, return NULL */
+		rnode.relNode = InvalidOid;
+		/* some compilers generate warnings without these next two lines */
+		rnode.dbNode = InvalidOid;
+		rnode.spcNode = InvalidOid;
 	}
 
 	if (!OidIsValid(rnode.relNode))
diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c
index c1120403fd..549bd64f6b 100644
--- a/src/backend/utils/adt/partitionfuncs.c
+++ b/src/backend/utils/adt/partitionfuncs.c
@@ -45,10 +45,25 @@ 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)
-		return false;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_PARTITIONED_INDEX:
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			if (!relispartition)
+				return false;
+			break;
+	}
 
 	return true;
 }
@@ -143,8 +158,25 @@ pg_partition_tree(PG_FUNCTION_ARGS)
 			nulls[1] = true;
 
 		/* isleaf */
-		values[2] = BoolGetDatum(relkind != RELKIND_PARTITIONED_TABLE &&
-								 relkind != RELKIND_PARTITIONED_INDEX);
+		switch ((RelKind) relkind)
+		{
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_PARTITIONED_INDEX:
+				values[2] = BoolGetDatum(false);
+				break;
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_VIEW:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				values[2] = BoolGetDatum(true);
+				break;
+		}
 
 		/* level */
 		if (relid != rootrelid)
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 509a0fdffc..821f91eb07 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -381,8 +381,23 @@ currtid_byreloid(PG_FUNCTION_ARGS)
 		aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
 					   RelationGetRelationName(rel));
 
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-		return currtid_for_view(rel, tid);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_VIEW:
+			return currtid_for_view(rel, tid);
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
 		elog(ERROR, "cannot look at latest visible tid for relation \"%s.%s\"",
@@ -423,8 +438,23 @@ currtid_byrelname(PG_FUNCTION_ARGS)
 		aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
 					   RelationGetRelationName(rel));
 
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-		return currtid_for_view(rel, tid);
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_VIEW:
+			return currtid_for_view(rel, tid);
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
 		elog(ERROR, "cannot look at latest visible tid for relation \"%s.%s\"",
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 4c299057a6..c2711075ef 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -2475,9 +2475,9 @@ schema_get_xml_visible_tables(Oid nspid)
 	initStringInfo(&query);
 	appendStringInfo(&query, "SELECT oid FROM pg_catalog.pg_class"
 					 " WHERE relnamespace = %u AND relkind IN ("
-					 CppAsString2(RELKIND_RELATION) ","
-					 CppAsString2(RELKIND_MATVIEW) ","
-					 CppAsString2(RELKIND_VIEW) ")"
+					 RelKindAsString(RELKIND_RELATION) ","
+					 RelKindAsString(RELKIND_MATVIEW) ","
+					 RelKindAsString(RELKIND_VIEW) ")"
 					 " AND pg_catalog.has_table_privilege (oid, 'SELECT')"
 					 " ORDER BY relname;", nspid);
 
@@ -2507,9 +2507,9 @@ database_get_xml_visible_tables(void)
 	/* At the moment there is no order required here. */
 	return query_to_oid_list("SELECT oid FROM pg_catalog.pg_class"
 							 " WHERE relkind IN ("
-							 CppAsString2(RELKIND_RELATION) ","
-							 CppAsString2(RELKIND_MATVIEW) ","
-							 CppAsString2(RELKIND_VIEW) ")"
+							 RelKindAsString(RELKIND_RELATION) ","
+							 RelKindAsString(RELKIND_MATVIEW) ","
+							 RelKindAsString(RELKIND_VIEW) ")"
 							 " AND pg_catalog.has_table_privilege(pg_class.oid, 'SELECT')"
 							 " AND relnamespace IN (" XML_VISIBLE_SCHEMAS ");");
 }
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index acf8a44f30..a5eef66f4e 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -53,8 +53,23 @@ static List *generate_partition_qual(Relation rel);
 PartitionKey
 RelationGetPartitionKey(Relation rel)
 {
-	if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-		return NULL;
+	switch ((RelKind) rel->rd_rel->relkind)
+	{
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			return NULL;
+	}
 
 	if (unlikely(rel->rd_partkey == NULL))
 		RelationBuildPartitionKey(rel);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 0b9eb00d2d..aa8f69224d 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -448,7 +448,7 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
 	 * Look up any AM-specific parse function; fall out if relkind should not
 	 * have options.
 	 */
-	switch (relation->rd_rel->relkind)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
@@ -461,6 +461,10 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
 		case RELKIND_PARTITIONED_INDEX:
 			amoptsfn = relation->rd_indam->amoptions;
 			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_NULL:
 		default:
 			return;
 	}
@@ -1181,7 +1185,7 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	/*
 	 * initialize access method information
 	 */
-	switch (relation->rd_rel->relkind)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
 		case RELKIND_INDEX:
 		case RELKIND_PARTITIONED_INDEX:
@@ -1202,6 +1206,8 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 		case RELKIND_COMPOSITE_TYPE:
 		case RELKIND_FOREIGN_TABLE:
 		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_NULL:
+		default:
 			Assert(relation->rd_rel->relam == InvalidOid);
 			break;
 	}
@@ -1746,38 +1752,53 @@ RelationInitTableAccessMethod(Relation relation)
 	HeapTuple	tuple;
 	Form_pg_am	aform;
 
-	if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
-	{
-		/*
-		 * Sequences are currently accessed like heap tables, but it doesn't
-		 * seem prudent to show that in the catalog. So just overwrite it
-		 * here.
-		 */
-		relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
-	}
-	else if (IsCatalogRelation(relation))
-	{
-		/*
-		 * Avoid doing a syscache lookup for catalog tables.
-		 */
-		Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
-		relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
-	}
-	else
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		/*
-		 * Look up the table 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",
-				 relation->rd_rel->relam);
-		aform = (Form_pg_am) GETSTRUCT(tuple);
-		relation->rd_amhandler = aform->amhandler;
-		ReleaseSysCache(tuple);
+		case RELKIND_SEQUENCE:
+
+			/*
+			 * Sequences are currently accessed like heap tables, but it
+			 * doesn't seem prudent to show that in the catalog. So just
+			 * overwrite it here.
+			 */
+			relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			if (IsCatalogRelation(relation))
+			{
+				/*
+				 * Avoid doing a syscache lookup for catalog tables.
+				 */
+				Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
+				relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
+			}
+			else
+			{
+				/*
+				 * Look up the table 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",
+						 relation->rd_rel->relam);
+				aform = (Form_pg_am) GETSTRUCT(tuple);
+				relation->rd_amhandler = aform->amhandler;
+				ReleaseSysCache(tuple);
+			}
+			break;
 	}
 
 	/*
@@ -2023,11 +2044,25 @@ RelationIdGetRelation(Oid relationId)
 			 * and we don't want to use the full-blown procedure because it's
 			 * a headache for indexes that reload itself depends on.
 			 */
-			if (rd->rd_rel->relkind == RELKIND_INDEX ||
-				rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-				RelationReloadIndexInfo(rd);
-			else
-				RelationClearRelation(rd, true);
+			switch ((RelKind) rd->rd_rel->relkind)
+			{
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_INDEX:
+					RelationReloadIndexInfo(rd);
+					break;
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					RelationClearRelation(rd, true);
+					break;
+			}
 
 			/*
 			 * Normally entries need to be valid here, but before the relcache
@@ -2284,46 +2319,60 @@ RelationReloadNailed(Relation relation)
 	if (!IsTransactionState() || relation->rd_refcnt <= 1)
 		return;
 
-	if (relation->rd_rel->relkind == RELKIND_INDEX)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		/*
-		 * If it's a nailed-but-not-mapped index, then we need to re-read the
-		 * pg_class row to see if its relfilenode changed.
-		 */
-		RelationReloadIndexInfo(relation);
-	}
-	else
-	{
-		/*
-		 * Reload a non-index entry.  We can't easily do so if relcaches
-		 * aren't yet built, but that's fine because at that stage the
-		 * attributes that need to be current (like relfrozenxid) aren't yet
-		 * accessed.  To ensure the entry will later be revalidated, we leave
-		 * it in invalid state, but allow use (cf. RelationIdGetRelation()).
-		 */
-		if (criticalRelcachesBuilt)
-		{
-			HeapTuple	pg_class_tuple;
-			Form_pg_class relp;
+		case RELKIND_INDEX:
 
 			/*
-			 * NB: Mark the entry as valid before starting to scan, to avoid
-			 * self-recursion when re-building pg_class.
+			 * If it's a nailed-but-not-mapped index, then we need to re-read
+			 * the pg_class row to see if its relfilenode changed.
 			 */
-			relation->rd_isvalid = true;
-
-			pg_class_tuple = ScanPgRelation(RelationGetRelid(relation),
-											true, false);
-			relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
-			memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
-			heap_freetuple(pg_class_tuple);
+			RelationReloadIndexInfo(relation);
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
 
 			/*
-			 * Again mark as valid, to protect against concurrently arriving
-			 * invalidations.
+			 * Reload a non-index entry.  We can't easily do so if relcaches
+			 * aren't yet built, but that's fine because at that stage the
+			 * attributes that need to be current (like relfrozenxid) aren't
+			 * yet accessed.  To ensure the entry will later be revalidated,
+			 * we leave it in invalid state, but allow use (cf.
+			 * RelationIdGetRelation()).
 			 */
-			relation->rd_isvalid = true;
-		}
+			if (criticalRelcachesBuilt)
+			{
+				HeapTuple	pg_class_tuple;
+				Form_pg_class relp;
+
+				/*
+				 * NB: Mark the entry as valid before starting to scan, to
+				 * avoid self-recursion when re-building pg_class.
+				 */
+				relation->rd_isvalid = true;
+
+				pg_class_tuple = ScanPgRelation(RelationGetRelid(relation),
+												true, false);
+				relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
+				memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
+				heap_freetuple(pg_class_tuple);
+
+				/*
+				 * Again mark as valid, to protect against concurrently
+				 * arriving invalidations.
+				 */
+				relation->rd_isvalid = true;
+			}
+			break;
 	}
 }
 
@@ -2470,14 +2519,28 @@ RelationClearRelation(Relation relation, bool rebuild)
 	 * re-read the pg_class row to handle possible physical relocation of the
 	 * index, and we check for pg_index updates too.
 	 */
-	if ((relation->rd_rel->relkind == RELKIND_INDEX ||
-		 relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
-		relation->rd_refcnt > 0 &&
-		relation->rd_indexcxt != NULL)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
-		if (IsTransactionState())
-			RelationReloadIndexInfo(relation);
-		return;
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			if (relation->rd_refcnt > 0 && relation->rd_indexcxt != NULL)
+			{
+				if (IsTransactionState())
+					RelationReloadIndexInfo(relation);
+				return;
+			}
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/*
@@ -3478,10 +3541,25 @@ RelationBuildLocalRelation(const char *relname,
 	}
 
 	/* if it's a materialized view, it's not populated initially */
-	if (relkind == RELKIND_MATVIEW)
-		rel->rd_rel->relispopulated = false;
-	else
-		rel->rd_rel->relispopulated = true;
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_MATVIEW:
+			rel->rd_rel->relispopulated = false;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			rel->rd_rel->relispopulated = true;
+			break;
+	}
 
 	/* set replica identity -- system catalogs and non-tables don't have one */
 	if (!IsCatalogNamespace(relnamespace) &&
@@ -3521,11 +3599,23 @@ RelationBuildLocalRelation(const char *relname,
 
 	rel->rd_rel->relam = accessmtd;
 
-	if (relkind == RELKIND_RELATION ||
-		relkind == RELKIND_SEQUENCE ||
-		relkind == RELKIND_TOASTVALUE ||
-		relkind == RELKIND_MATVIEW)
-		RelationInitTableAccessMethod(rel);
+	switch ((RelKind) relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_SEQUENCE:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_MATVIEW:
+			RelationInitTableAccessMethod(rel);
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/*
 	 * Okay to insert into the relcache hash table.
@@ -3618,7 +3708,7 @@ RelationSetNewRelfilenode(Relation relation, char persistence)
 	newrnode = relation->rd_node;
 	newrnode.relNode = newrelfilenode;
 
-	switch (relation->rd_rel->relkind)
+	switch ((RelKind) relation->rd_rel->relkind)
 	{
 		case RELKIND_INDEX:
 		case RELKIND_SEQUENCE:
@@ -3630,7 +3720,6 @@ RelationSetNewRelfilenode(Relation relation, char persistence)
 				smgrclose(srel);
 			}
 			break;
-
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
@@ -3638,7 +3727,12 @@ RelationSetNewRelfilenode(Relation relation, char persistence)
 											persistence,
 											&freezeXid, &minmulti);
 			break;
-
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
 		default:
 			/* we shouldn't be called for anything else */
 			elog(ERROR, "relation \"%s\" does not have storage",
@@ -3688,11 +3782,25 @@ RelationSetNewRelfilenode(Relation relation, char persistence)
 		classform->relfilenode = newrelfilenode;
 
 		/* relpages etc. never change for sequences */
-		if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
+		switch ((RelKind) relation->rd_rel->relkind)
 		{
-			classform->relpages = 0;	/* it's empty until further notice */
-			classform->reltuples = 0;
-			classform->relallvisible = 0;
+			case RELKIND_SEQUENCE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				classform->relpages = 0;	/* it's empty until further notice */
+				classform->reltuples = 0;
+				classform->relallvisible = 0;
+				break;
 		}
 		classform->relfrozenxid = freezeXid;
 		classform->relminmxid = minmulti;
@@ -4085,16 +4193,29 @@ 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))
+		switch ((RelKind) relation->rd_rel->relkind)
 		{
-			RelationInitTableAccessMethod(relation);
-			Assert(relation->rd_tableam != NULL);
+			case RELKIND_RELATION:
+			case RELKIND_SEQUENCE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_MATVIEW:
+				if (relation->rd_tableam == NULL)
+				{
+					RelationInitTableAccessMethod(relation);
+					Assert(relation->rd_tableam != NULL);
 
-			restart = true;
+					restart = true;
+				}
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/* Release hold on the relation */
@@ -5863,11 +5984,24 @@ 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)
-				RelationInitTableAccessMethod(rel);
+			switch ((RelKind) rel->rd_rel->relkind)
+			{
+				case RELKIND_RELATION:
+				case RELKIND_SEQUENCE:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_MATVIEW:
+					RelationInitTableAccessMethod(rel);
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					break;
+			}
 
 			Assert(rel->rd_index == NULL);
 			Assert(rel->rd_indextuple == NULL);
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 786672b1b6..3b0cf8a234 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1743,12 +1743,12 @@ setup_privileges(FILE *cmdfd)
 		"  SET relacl = (SELECT array_agg(a.acl) FROM "
 		" (SELECT E'=r/\"$POSTGRES_SUPERUSERNAME\"' as acl "
 		"  UNION SELECT unnest(pg_catalog.acldefault("
-		"    CASE WHEN relkind = " CppAsString2(RELKIND_SEQUENCE) " THEN 's' "
+		"    CASE WHEN relkind = " RelKindAsString(RELKIND_SEQUENCE) " THEN 's' "
 		"         ELSE 'r' END::\"char\"," CppAsString2(BOOTSTRAP_SUPERUSERID) "::oid))"
 		" ) as a) "
-		"  WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-		CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
-		CppAsString2(RELKIND_SEQUENCE) ")"
+		"  WHERE relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+		RelKindAsString(RELKIND_VIEW) ", " RelKindAsString(RELKIND_MATVIEW) ", "
+		RelKindAsString(RELKIND_SEQUENCE) ")"
 		"  AND relacl IS NULL;\n\n",
 		"GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n",
 		"GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n",
@@ -1765,9 +1765,9 @@ setup_privileges(FILE *cmdfd)
 		"        pg_class"
 		"    WHERE"
 		"        relacl IS NOT NULL"
-		"        AND relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-		CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
-		CppAsString2(RELKIND_SEQUENCE) ");\n\n",
+		"        AND relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+		RelKindAsString(RELKIND_VIEW) ", " RelKindAsString(RELKIND_MATVIEW) ", "
+		RelKindAsString(RELKIND_SEQUENCE) ");\n\n",
 		"INSERT INTO pg_init_privs "
 		"  (objoid, classoid, objsubid, initprivs, privtype)"
 		"    SELECT"
@@ -1781,9 +1781,9 @@ setup_privileges(FILE *cmdfd)
 		"        JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)"
 		"    WHERE"
 		"        pg_attribute.attacl IS NOT NULL"
-		"        AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-		CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
-		CppAsString2(RELKIND_SEQUENCE) ");\n\n",
+		"        AND pg_class.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+		RelKindAsString(RELKIND_VIEW) ", " RelKindAsString(RELKIND_MATVIEW) ", "
+		RelKindAsString(RELKIND_SEQUENCE) ");\n\n",
 		"INSERT INTO pg_init_privs "
 		"  (objoid, classoid, objsubid, initprivs, privtype)"
 		"    SELECT"
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 4ea59f5494..cc85c9ef15 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -283,10 +283,23 @@ flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
 		bool		mark_parents = true;
 
 		/* Some kinds never have parents */
-		if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
-			tblinfo[i].relkind == RELKIND_VIEW ||
-			tblinfo[i].relkind == RELKIND_MATVIEW)
-			continue;
+		switch ((RelKind) tblinfo[i].relkind)
+		{
+			case RELKIND_SEQUENCE:
+			case RELKIND_VIEW:
+			case RELKIND_MATVIEW:
+				continue;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		/*
 		 * Normally, we don't bother computing anything for non-target tables,
@@ -449,10 +462,23 @@ flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables)
 		TableInfo **parents;
 
 		/* Some kinds never have parents */
-		if (tbinfo->relkind == RELKIND_SEQUENCE ||
-			tbinfo->relkind == RELKIND_VIEW ||
-			tbinfo->relkind == RELKIND_MATVIEW)
-			continue;
+		switch ((RelKind) tbinfo->relkind)
+		{
+			case RELKIND_SEQUENCE:
+			case RELKIND_VIEW:
+			case RELKIND_MATVIEW:
+				continue;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		/* Don't bother computing anything for non-target tables, either */
 		if (!tbinfo->dobj.dump)
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index b4f5942959..0b04578b9a 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -1191,7 +1191,7 @@ _tarPositionTo(ArchiveHandle *AH, const char *filename)
 		/* Header doesn't match, so read to next header */
 		len = th->fileLen;
 		len += tarPaddingBytesRequired(th->fileLen);
-		blks = len / TAR_BLOCK_SIZE;		/* # of tar blocks */
+		blks = len / TAR_BLOCK_SIZE;	/* # of tar blocks */
 
 		for (i = 0; i < blks; i++)
 			_tarReadRaw(AH, &header[0], TAR_BLOCK_SIZE, NULL, ctx->tarFH);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index a41a3db876..9fcdf0ddbc 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2399,17 +2399,35 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
 		return;
 
 	/* Skip VIEWs (no data to dump) */
-	if (tbinfo->relkind == RELKIND_VIEW)
-		return;
-	/* Skip FOREIGN TABLEs (no data to dump) unless requested explicitly */
-	if (tbinfo->relkind == RELKIND_FOREIGN_TABLE &&
-		(foreign_servers_include_oids.head == NULL ||
-		 !simple_oid_list_member(&foreign_servers_include_oids,
-								 tbinfo->foreign_server)))
-		return;
-	/* Skip partitioned tables (data in partitions) */
-	if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
-		return;
+	switch ((RelKind) tbinfo->relkind)
+	{
+		case RELKIND_VIEW:
+			return;
+
+			/*
+			 * Skip FOREIGN TABLEs (no data to dump) unless requested
+			 * explicitly
+			 */
+		case RELKIND_FOREIGN_TABLE:
+			if (foreign_servers_include_oids.head == NULL ||
+				!simple_oid_list_member(&foreign_servers_include_oids,
+										tbinfo->foreign_server))
+				return;
+			break;
+			/* Skip partitioned tables (data in partitions) */
+		case RELKIND_PARTITIONED_TABLE:
+			return;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
+	}
 
 	/* Don't dump data in unlogged tables, if so requested */
 	if (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED &&
@@ -2424,12 +2442,27 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
 	/* OK, let's dump it */
 	tdinfo = (TableDataInfo *) pg_malloc(sizeof(TableDataInfo));
 
-	if (tbinfo->relkind == RELKIND_MATVIEW)
-		tdinfo->dobj.objType = DO_REFRESH_MATVIEW;
-	else if (tbinfo->relkind == RELKIND_SEQUENCE)
-		tdinfo->dobj.objType = DO_SEQUENCE_SET;
-	else
-		tdinfo->dobj.objType = DO_TABLE_DATA;
+	switch ((RelKind) tbinfo->relkind)
+	{
+		case RELKIND_MATVIEW:
+			tdinfo->dobj.objType = DO_REFRESH_MATVIEW;
+			break;
+		case RELKIND_SEQUENCE:
+			tdinfo->dobj.objType = DO_SEQUENCE_SET;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			tdinfo->dobj.objType = DO_TABLE_DATA;
+			break;
+	}
 
 	/*
 	 * Note: use tableoid 0 so that this object won't be mistaken for
@@ -2476,14 +2509,14 @@ buildMatViewRefreshDependencies(Archive *fout)
 						 "SELECT d1.objid, d2.refobjid, c2.relkind AS refrelkind "
 						 "FROM pg_depend d1 "
 						 "JOIN pg_class c1 ON c1.oid = d1.objid "
-						 "AND c1.relkind = " CppAsString2(RELKIND_MATVIEW)
+						 "AND c1.relkind = " RelKindAsString(RELKIND_MATVIEW)
 						 " JOIN pg_rewrite r1 ON r1.ev_class = d1.objid "
 						 "JOIN pg_depend d2 ON d2.classid = 'pg_rewrite'::regclass "
 						 "AND d2.objid = r1.oid "
 						 "AND d2.refobjid <> d1.objid "
 						 "JOIN pg_class c2 ON c2.oid = d2.refobjid "
-						 "AND c2.relkind IN (" CppAsString2(RELKIND_MATVIEW) ","
-						 CppAsString2(RELKIND_VIEW) ") "
+						 "AND c2.relkind IN (" RelKindAsString(RELKIND_MATVIEW) ","
+						 RelKindAsString(RELKIND_VIEW) ") "
 						 "WHERE d1.classid = 'pg_class'::regclass "
 						 "UNION "
 						 "SELECT w.objid, d3.refobjid, c3.relkind "
@@ -2493,12 +2526,12 @@ buildMatViewRefreshDependencies(Archive *fout)
 						 "AND d3.objid = r3.oid "
 						 "AND d3.refobjid <> w.refobjid "
 						 "JOIN pg_class c3 ON c3.oid = d3.refobjid "
-						 "AND c3.relkind IN (" CppAsString2(RELKIND_MATVIEW) ","
-						 CppAsString2(RELKIND_VIEW) ") "
+						 "AND c3.relkind IN (" RelKindAsString(RELKIND_MATVIEW) ","
+						 RelKindAsString(RELKIND_VIEW) ") "
 						 ") "
 						 "SELECT 'pg_class'::regclass::oid AS classid, objid, refobjid "
 						 "FROM w "
-						 "WHERE refrelkind = " CppAsString2(RELKIND_MATVIEW));
+						 "WHERE refrelkind = " RelKindAsString(RELKIND_MATVIEW));
 
 	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -2637,9 +2670,23 @@ guessConstraintInheritance(TableInfo *tblinfo, int numTables)
 		TableInfo  *parent;
 
 		/* Sequences and views never have parents */
-		if (tbinfo->relkind == RELKIND_SEQUENCE ||
-			tbinfo->relkind == RELKIND_VIEW)
-			continue;
+		switch ((RelKind) tbinfo->relkind)
+		{
+			case RELKIND_SEQUENCE:
+			case RELKIND_VIEW:
+				continue;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 
 		/* Don't bother computing anything for non-target tables, either */
 		if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
@@ -4068,9 +4115,23 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
 		/*
 		 * Only regular and partitioned tables can be added to publications.
 		 */
-		if (tbinfo->relkind != RELKIND_RELATION &&
-			tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
-			continue;
+		switch ((RelKind) tbinfo->relkind)
+		{
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_TABLE:
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				continue;
+		}
 
 		/*
 		 * Ignore publication membership of tables whose definitions are not
@@ -6157,7 +6218,7 @@ getTables(Archive *fout, int *numTables)
 
 		buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
 						initracl_subquery, "c.relacl", "c.relowner",
-						"CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE)
+						"CASE WHEN c.relkind = " RelKindAsString(RELKIND_SEQUENCE)
 						" THEN 's' ELSE 'r' END::\"char\"",
 						dopt->binary_upgrade);
 
@@ -6786,10 +6847,25 @@ getTables(Archive *fout, int *numTables)
 		/*
 		 * Decide whether we want to dump this table.
 		 */
-		if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
-			tblinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
-		else
-			selectDumpableTable(&tblinfo[i], fout);
+		switch ((RelKind) tblinfo[i].relkind)
+		{
+			case RELKIND_COMPOSITE_TYPE:
+				tblinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				selectDumpableTable(&tblinfo[i], fout);
+				break;
+		}
 
 		/*
 		 * If the table-level and all column-level ACLs for this table are
@@ -6836,16 +6912,31 @@ getTables(Archive *fout, int *numTables)
 		 * We only need to lock the table for certain components; see
 		 * pg_dump.h
 		 */
-		if (tblinfo[i].dobj.dump &&
-			(tblinfo[i].relkind == RELKIND_RELATION ||
-			 tblinfo->relkind == RELKIND_PARTITIONED_TABLE) &&
-			(tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
+		switch ((RelKind) tblinfo[i].relkind)
 		{
-			resetPQExpBuffer(query);
-			appendPQExpBuffer(query,
-							  "LOCK TABLE %s IN ACCESS SHARE MODE",
-							  fmtQualifiedDumpable(&tblinfo[i]));
-			ExecuteSqlStatement(fout, query->data);
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_TABLE:
+				if (tblinfo[i].dobj.dump &&
+					(tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
+				{
+					resetPQExpBuffer(query);
+					appendPQExpBuffer(query,
+									  "LOCK TABLE %s IN ACCESS SHARE MODE",
+									  fmtQualifiedDumpable(&tblinfo[i]));
+					ExecuteSqlStatement(fout, query->data);
+				}
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/* Emit notice if join for owner failed */
@@ -15749,7 +15840,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 		char	   *srvname = NULL;
 		char	   *foreign = "";
 
-		switch (tbinfo->relkind)
+		switch ((RelKind) tbinfo->relkind)
 		{
 			case RELKIND_FOREIGN_TABLE:
 				{
@@ -15788,8 +15879,21 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 			case RELKIND_MATVIEW:
 				reltypename = "MATERIALIZED VIEW";
 				break;
-			default:
+			case RELKIND_RELATION:
+			case RELKIND_PARTITIONED_TABLE:
 				reltypename = "TABLE";
+				break;
+			case RELKIND_SEQUENCE:
+			case RELKIND_VIEW:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				Assert(false);
+				reltypename = "XXX";
+				break;
 		}
 
 		numParents = tbinfo->numParents;
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 654e2ec514..1e1da953c8 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -801,8 +801,24 @@ repairMatViewBoundaryMultiLoop(DumpableObject *boundaryobj,
 	{
 		TableInfo  *nextinfo = (TableInfo *) nextobj;
 
-		if (nextinfo->relkind == RELKIND_MATVIEW)
-			nextinfo->postponed_def = true;
+		switch ((RelKind) nextinfo->relkind)
+		{
+			case RELKIND_MATVIEW:
+				nextinfo->postponed_def = true;
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_TABLE:
+			case RELKIND_RELATION:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
+		}
 	}
 }
 
@@ -928,30 +944,61 @@ repairDependencyLoop(DumpableObject **loop,
 		return;
 	}
 
-	/* View (including matview) and its ON SELECT rule */
-	if (nLoop == 2 &&
-		loop[0]->objType == DO_TABLE &&
-		loop[1]->objType == DO_RULE &&
-		(((TableInfo *) loop[0])->relkind == RELKIND_VIEW ||
-		 ((TableInfo *) loop[0])->relkind == RELKIND_MATVIEW) &&
-		((RuleInfo *) loop[1])->ev_type == '1' &&
-		((RuleInfo *) loop[1])->is_instead &&
-		((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0])
+	switch ((RelKind) ((TableInfo *) loop[0])->relkind)
 	{
-		repairViewRuleLoop(loop[0], loop[1]);
-		return;
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+			/* View (including matview) and its ON SELECT rule */
+			if (nLoop == 2 &&
+				loop[0]->objType == DO_TABLE &&
+				loop[1]->objType == DO_RULE &&
+				((RuleInfo *) loop[1])->ev_type == '1' &&
+				((RuleInfo *) loop[1])->is_instead &&
+				((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0])
+			{
+				repairViewRuleLoop(loop[0], loop[1]);
+				return;
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
-	if (nLoop == 2 &&
-		loop[1]->objType == DO_TABLE &&
-		loop[0]->objType == DO_RULE &&
-		(((TableInfo *) loop[1])->relkind == RELKIND_VIEW ||
-		 ((TableInfo *) loop[1])->relkind == RELKIND_MATVIEW) &&
-		((RuleInfo *) loop[0])->ev_type == '1' &&
-		((RuleInfo *) loop[0])->is_instead &&
-		((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1])
+
+	switch ((RelKind) ((TableInfo *) loop[1])->relkind)
 	{
-		repairViewRuleLoop(loop[1], loop[0]);
-		return;
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+			if (nLoop == 2 &&
+				loop[1]->objType == DO_TABLE &&
+				loop[0]->objType == DO_RULE &&
+				((RuleInfo *) loop[0])->ev_type == '1' &&
+				((RuleInfo *) loop[0])->is_instead &&
+				((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1])
+			{
+				repairViewRuleLoop(loop[1], loop[0]);
+				return;
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* Indirect loop involving view (but not matview) and ON SELECT rule */
@@ -959,20 +1006,36 @@ repairDependencyLoop(DumpableObject **loop,
 	{
 		for (i = 0; i < nLoop; i++)
 		{
-			if (loop[i]->objType == DO_TABLE &&
-				((TableInfo *) loop[i])->relkind == RELKIND_VIEW)
+			switch ((RelKind) ((TableInfo *) loop[i])->relkind)
 			{
-				for (j = 0; j < nLoop; j++)
-				{
-					if (loop[j]->objType == DO_RULE &&
-						((RuleInfo *) loop[j])->ev_type == '1' &&
-						((RuleInfo *) loop[j])->is_instead &&
-						((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i])
+				case RELKIND_VIEW:
+					if (loop[i]->objType == DO_TABLE)
 					{
-						repairViewRuleMultiLoop(loop[i], loop[j]);
-						return;
+						for (j = 0; j < nLoop; j++)
+						{
+							if (loop[j]->objType == DO_RULE &&
+								((RuleInfo *) loop[j])->ev_type == '1' &&
+								((RuleInfo *) loop[j])->is_instead &&
+								((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i])
+							{
+								repairViewRuleMultiLoop(loop[i], loop[j]);
+								return;
+							}
+						}
 					}
-				}
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_MATVIEW:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 		}
 	}
@@ -982,20 +1045,36 @@ repairDependencyLoop(DumpableObject **loop,
 	{
 		for (i = 0; i < nLoop; i++)
 		{
-			if (loop[i]->objType == DO_TABLE &&
-				((TableInfo *) loop[i])->relkind == RELKIND_MATVIEW)
+			switch ((RelKind) ((TableInfo *) loop[i])->relkind)
 			{
-				for (j = 0; j < nLoop; j++)
-				{
-					if (loop[j]->objType == DO_PRE_DATA_BOUNDARY)
+				case RELKIND_MATVIEW:
+					if (loop[i]->objType == DO_TABLE)
 					{
-						DumpableObject *nextobj;
-
-						nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
-						repairMatViewBoundaryMultiLoop(loop[j], nextobj);
-						return;
+						for (j = 0; j < nLoop; j++)
+						{
+							if (loop[j]->objType == DO_PRE_DATA_BOUNDARY)
+							{
+								DumpableObject *nextobj;
+
+								nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
+								repairMatViewBoundaryMultiLoop(loop[j], nextobj);
+								return;
+							}
+						}
 					}
-				}
+					break;
+				case RELKIND_PARTITIONED_INDEX:
+				case RELKIND_SEQUENCE:
+				case RELKIND_COMPOSITE_TYPE:
+				case RELKIND_FOREIGN_TABLE:
+				case RELKIND_INDEX:
+				case RELKIND_PARTITIONED_TABLE:
+				case RELKIND_RELATION:
+				case RELKIND_TOASTVALUE:
+				case RELKIND_VIEW:
+				case RELKIND_NULL:
+				default:
+					break;
 			}
 		}
 	}
diff --git a/src/bin/pg_upgrade/info.c b/src/bin/pg_upgrade/info.c
index 7e524ea192..d67da370c5 100644
--- a/src/bin/pg_upgrade/info.c
+++ b/src/bin/pg_upgrade/info.c
@@ -446,8 +446,8 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
 			 "  SELECT c.oid, 0::oid, 0::oid "
 			 "  FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
 			 "         ON c.relnamespace = n.oid "
-			 "  WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-			 CppAsString2(RELKIND_MATVIEW) ") AND "
+			 "  WHERE relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+			 RelKindAsString(RELKIND_MATVIEW) ") AND "
 	/* exclude possible orphaned temp tables */
 			 "    ((n.nspname !~ '^pg_temp_' AND "
 			 "      n.nspname !~ '^pg_toast_temp_' AND "
diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c
index 70194eb096..996bf8bf70 100644
--- a/src/bin/pg_upgrade/pg_upgrade.c
+++ b/src/bin/pg_upgrade/pg_upgrade.c
@@ -643,9 +643,9 @@ set_frozenxids(bool minmxid_only)
 									  "SET	relfrozenxid = '%u' "
 			/* only heap, materialized view, and TOAST are vacuumed */
 									  "WHERE	relkind IN ("
-									  CppAsString2(RELKIND_RELATION) ", "
-									  CppAsString2(RELKIND_MATVIEW) ", "
-									  CppAsString2(RELKIND_TOASTVALUE) ")",
+									  RelKindAsString(RELKIND_RELATION) ", "
+									  RelKindAsString(RELKIND_MATVIEW) ", "
+									  RelKindAsString(RELKIND_TOASTVALUE) ")",
 									  old_cluster.controldata.chkpnt_nxtxid));
 
 		/* set pg_class.relminmxid */
@@ -654,9 +654,9 @@ set_frozenxids(bool minmxid_only)
 								  "SET	relminmxid = '%u' "
 		/* only heap, materialized view, and TOAST are vacuumed */
 								  "WHERE	relkind IN ("
-								  CppAsString2(RELKIND_RELATION) ", "
-								  CppAsString2(RELKIND_MATVIEW) ", "
-								  CppAsString2(RELKIND_TOASTVALUE) ")",
+								  RelKindAsString(RELKIND_RELATION) ", "
+								  RelKindAsString(RELKIND_MATVIEW) ", "
+								  RelKindAsString(RELKIND_TOASTVALUE) ")",
 								  old_cluster.controldata.chkpnt_nxtmulti));
 		PQfinish(conn);
 
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index 4e5d27f76e..5fb158c093 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -176,9 +176,9 @@ check_for_data_type_usage(ClusterInfo *cluster, const char *typename,
 						  "		NOT a.attisdropped AND "
 						  "		a.atttypid IN (SELECT oid FROM oids) AND "
 						  "		c.relkind IN ("
-						  CppAsString2(RELKIND_RELATION) ", "
-						  CppAsString2(RELKIND_MATVIEW) ", "
-						  CppAsString2(RELKIND_INDEX) ") AND "
+						  RelKindAsString(RELKIND_RELATION) ", "
+						  RelKindAsString(RELKIND_MATVIEW) ", "
+						  RelKindAsString(RELKIND_INDEX) ") AND "
 						  "		c.relnamespace = n.oid AND "
 		/* exclude possible orphaned temp tables */
 						  "		n.nspname !~ '^pg_temp_' AND "
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 560eacc7f0..5e0f7f92c6 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -4942,16 +4942,25 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid,
 					 * does not, so editing a matview definition in this way
 					 * is impossible.
 					 */
-					switch (relkind[0])
+					switch ((RelKind) relkind[0])
 					{
-#ifdef NOT_USED
+						case RELKIND_VIEW:
+							appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
+							break;
 						case RELKIND_MATVIEW:
+#ifdef NOT_USED
 							appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
 							break;
 #endif
-						case RELKIND_VIEW:
-							appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
-							break;
+						case RELKIND_PARTITIONED_INDEX:
+						case RELKIND_SEQUENCE:
+						case RELKIND_COMPOSITE_TYPE:
+						case RELKIND_FOREIGN_TABLE:
+						case RELKIND_INDEX:
+						case RELKIND_PARTITIONED_TABLE:
+						case RELKIND_RELATION:
+						case RELKIND_TOASTVALUE:
+						case RELKIND_NULL:
 						default:
 							pg_log_error("\"%s.%s\" is not a view",
 										 nspname, relname);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index cd39b913cd..67675cc0c3 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -734,7 +734,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
 	 * composite types
 	 */
 	appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 ");
-	appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
+	appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = " RelKindAsString(RELKIND_COMPOSITE_TYPE)
 						 " FROM pg_catalog.pg_class c "
 						 "WHERE c.oid = t.typrelid))\n");
 
@@ -943,12 +943,12 @@ permissionsList(const char *pattern)
 					  "SELECT n.nspname as \"%s\",\n"
 					  "  c.relname as \"%s\",\n"
 					  "  CASE c.relkind"
-					  " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_RELATION) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_VIEW) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_MATVIEW) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_SEQUENCE) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_FOREIGN_TABLE) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
 					  " END as \"%s\",\n"
 					  "  ",
 					  gettext_noop("Schema"),
@@ -1040,12 +1040,12 @@ permissionsList(const char *pattern)
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n"
 						 "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
 						 "WHERE c.relkind IN ("
-						 CppAsString2(RELKIND_RELATION) ","
-						 CppAsString2(RELKIND_VIEW) ","
-						 CppAsString2(RELKIND_MATVIEW) ","
-						 CppAsString2(RELKIND_SEQUENCE) ","
-						 CppAsString2(RELKIND_FOREIGN_TABLE) ","
-						 CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
+						 RelKindAsString(RELKIND_RELATION) ","
+						 RelKindAsString(RELKIND_VIEW) ","
+						 RelKindAsString(RELKIND_MATVIEW) ","
+						 RelKindAsString(RELKIND_SEQUENCE) ","
+						 RelKindAsString(RELKIND_FOREIGN_TABLE) ","
+						 RelKindAsString(RELKIND_PARTITIONED_TABLE) ")\n");
 
 	/*
 	 * Unless a schema pattern is specified, we suppress system and temp
@@ -1692,134 +1692,148 @@ describeOneTableDetails(const char *schemaname,
 	/*
 	 * If it's a sequence, deal with it here separately.
 	 */
-	if (tableinfo.relkind == RELKIND_SEQUENCE)
+	switch ((RelKind) tableinfo.relkind)
 	{
-		PGresult   *result = NULL;
-		printQueryOpt myopt = pset.popt;
-		char	   *footers[2] = {NULL, NULL};
-
-		if (pset.sversion >= 100000)
-		{
-			printfPQExpBuffer(&buf,
-							  "SELECT pg_catalog.format_type(seqtypid, NULL) AS \"%s\",\n"
-							  "       seqstart AS \"%s\",\n"
-							  "       seqmin AS \"%s\",\n"
-							  "       seqmax AS \"%s\",\n"
-							  "       seqincrement AS \"%s\",\n"
-							  "       CASE WHEN seqcycle THEN '%s' ELSE '%s' END AS \"%s\",\n"
-							  "       seqcache AS \"%s\"\n",
-							  gettext_noop("Type"),
-							  gettext_noop("Start"),
-							  gettext_noop("Minimum"),
-							  gettext_noop("Maximum"),
-							  gettext_noop("Increment"),
-							  gettext_noop("yes"),
-							  gettext_noop("no"),
-							  gettext_noop("Cycles?"),
-							  gettext_noop("Cache"));
-			appendPQExpBuffer(&buf,
-							  "FROM pg_catalog.pg_sequence\n"
-							  "WHERE seqrelid = '%s';",
-							  oid);
-		}
-		else
-		{
-			printfPQExpBuffer(&buf,
-							  "SELECT 'bigint' AS \"%s\",\n"
-							  "       start_value AS \"%s\",\n"
-							  "       min_value AS \"%s\",\n"
-							  "       max_value AS \"%s\",\n"
-							  "       increment_by AS \"%s\",\n"
-							  "       CASE WHEN is_cycled THEN '%s' ELSE '%s' END AS \"%s\",\n"
-							  "       cache_value AS \"%s\"\n",
-							  gettext_noop("Type"),
-							  gettext_noop("Start"),
-							  gettext_noop("Minimum"),
-							  gettext_noop("Maximum"),
-							  gettext_noop("Increment"),
-							  gettext_noop("yes"),
-							  gettext_noop("no"),
-							  gettext_noop("Cycles?"),
-							  gettext_noop("Cache"));
-			appendPQExpBuffer(&buf, "FROM %s", fmtId(schemaname));
-			/* must be separate because fmtId isn't reentrant */
-			appendPQExpBuffer(&buf, ".%s;", fmtId(relationname));
-		}
+		case RELKIND_SEQUENCE:
+			{
+				PGresult   *result = NULL;
+				printQueryOpt myopt = pset.popt;
+				char	   *footers[2] = {NULL, NULL};
 
-		res = PSQLexec(buf.data);
-		if (!res)
-			goto error_return;
+				if (pset.sversion >= 100000)
+				{
+					printfPQExpBuffer(&buf,
+									  "SELECT pg_catalog.format_type(seqtypid, NULL) AS \"%s\",\n"
+									  "       seqstart AS \"%s\",\n"
+									  "       seqmin AS \"%s\",\n"
+									  "       seqmax AS \"%s\",\n"
+									  "       seqincrement AS \"%s\",\n"
+									  "       CASE WHEN seqcycle THEN '%s' ELSE '%s' END AS \"%s\",\n"
+									  "       seqcache AS \"%s\"\n",
+									  gettext_noop("Type"),
+									  gettext_noop("Start"),
+									  gettext_noop("Minimum"),
+									  gettext_noop("Maximum"),
+									  gettext_noop("Increment"),
+									  gettext_noop("yes"),
+									  gettext_noop("no"),
+									  gettext_noop("Cycles?"),
+									  gettext_noop("Cache"));
+					appendPQExpBuffer(&buf,
+									  "FROM pg_catalog.pg_sequence\n"
+									  "WHERE seqrelid = '%s';",
+									  oid);
+				}
+				else
+				{
+					printfPQExpBuffer(&buf,
+									  "SELECT 'bigint' AS \"%s\",\n"
+									  "       start_value AS \"%s\",\n"
+									  "       min_value AS \"%s\",\n"
+									  "       max_value AS \"%s\",\n"
+									  "       increment_by AS \"%s\",\n"
+									  "       CASE WHEN is_cycled THEN '%s' ELSE '%s' END AS \"%s\",\n"
+									  "       cache_value AS \"%s\"\n",
+									  gettext_noop("Type"),
+									  gettext_noop("Start"),
+									  gettext_noop("Minimum"),
+									  gettext_noop("Maximum"),
+									  gettext_noop("Increment"),
+									  gettext_noop("yes"),
+									  gettext_noop("no"),
+									  gettext_noop("Cycles?"),
+									  gettext_noop("Cache"));
+					appendPQExpBuffer(&buf, "FROM %s", fmtId(schemaname));
+					/* must be separate because fmtId isn't reentrant */
+					appendPQExpBuffer(&buf, ".%s;", fmtId(relationname));
+				}
 
-		/* Footer information about a sequence */
+				res = PSQLexec(buf.data);
+				if (!res)
+					goto error_return;
+
+				/* Footer information about a sequence */
+
+				/* Get the column that owns this sequence */
+				printfPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||"
+								  "\n   pg_catalog.quote_ident(relname) || '.' ||"
+								  "\n   pg_catalog.quote_ident(attname),"
+								  "\n   d.deptype"
+								  "\nFROM pg_catalog.pg_class c"
+								  "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid"
+								  "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace"
+								  "\nINNER JOIN pg_catalog.pg_attribute a ON ("
+								  "\n a.attrelid=c.oid AND"
+								  "\n a.attnum=d.refobjsubid)"
+								  "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass"
+								  "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass"
+								  "\n AND d.objid='%s'"
+								  "\n AND d.deptype IN ('a', 'i')",
+								  oid);
 
-		/* Get the column that owns this sequence */
-		printfPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||"
-						  "\n   pg_catalog.quote_ident(relname) || '.' ||"
-						  "\n   pg_catalog.quote_ident(attname),"
-						  "\n   d.deptype"
-						  "\nFROM pg_catalog.pg_class c"
-						  "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid"
-						  "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace"
-						  "\nINNER JOIN pg_catalog.pg_attribute a ON ("
-						  "\n a.attrelid=c.oid AND"
-						  "\n a.attnum=d.refobjsubid)"
-						  "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass"
-						  "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass"
-						  "\n AND d.objid='%s'"
-						  "\n AND d.deptype IN ('a', 'i')",
-						  oid);
+				result = PSQLexec(buf.data);
 
-		result = PSQLexec(buf.data);
+				/*
+				 * If we get no rows back, don't show anything (obviously). We
+				 * should never get more than one row back, but if we do, just
+				 * ignore it and don't print anything.
+				 */
+				if (!result)
+					goto error_return;
+				else if (PQntuples(result) == 1)
+				{
+					switch (PQgetvalue(result, 0, 1)[0])
+					{
+						case 'a':
+							footers[0] = psprintf(_("Owned by: %s"),
+												  PQgetvalue(result, 0, 0));
+							break;
+						case 'i':
+							footers[0] = psprintf(_("Sequence for identity column: %s"),
+												  PQgetvalue(result, 0, 0));
+							break;
+					}
+				}
+				PQclear(result);
 
-		/*
-		 * If we get no rows back, don't show anything (obviously). We should
-		 * never get more than one row back, but if we do, just ignore it and
-		 * don't print anything.
-		 */
-		if (!result)
-			goto error_return;
-		else if (PQntuples(result) == 1)
-		{
-			switch (PQgetvalue(result, 0, 1)[0])
-			{
-				case 'a':
-					footers[0] = psprintf(_("Owned by: %s"),
-										  PQgetvalue(result, 0, 0));
-					break;
-				case 'i':
-					footers[0] = psprintf(_("Sequence for identity column: %s"),
-										  PQgetvalue(result, 0, 0));
-					break;
-			}
-		}
-		PQclear(result);
+				printfPQExpBuffer(&title, _("Sequence \"%s.%s\""),
+								  schemaname, relationname);
 
-		printfPQExpBuffer(&title, _("Sequence \"%s.%s\""),
-						  schemaname, relationname);
+				myopt.footers = footers;
+				myopt.topt.default_footer = false;
+				myopt.title = title.data;
+				myopt.translate_header = true;
 
-		myopt.footers = footers;
-		myopt.topt.default_footer = false;
-		myopt.title = title.data;
-		myopt.translate_header = true;
+				printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
-		printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+				if (footers[0])
+					free(footers[0]);
 
-		if (footers[0])
-			free(footers[0]);
+				retval = true;
+				goto error_return;	/* not an error, just return early */
+			}
+			break;
 
-		retval = true;
-		goto error_return;		/* not an error, just return early */
+			/*
+			 * Identify whether we should print collation, nullable, default
+			 * vals
+			 */
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_PARTITIONED_TABLE:
+			show_column_details = true;
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
-	/* Identify whether we should print collation, nullable, default vals */
-	if (tableinfo.relkind == RELKIND_RELATION ||
-		tableinfo.relkind == RELKIND_VIEW ||
-		tableinfo.relkind == RELKIND_MATVIEW ||
-		tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
-		tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
-		tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
-		show_column_details = true;
-
 	/*
 	 * Get per-column info
 	 *
@@ -1861,58 +1875,91 @@ describeOneTableDetails(const char *schemaname,
 			appendPQExpBufferStr(&buf, ",\n  ''::pg_catalog.char AS attgenerated");
 		attgenerated_col = cols++;
 	}
-	if (tableinfo.relkind == RELKIND_INDEX ||
-		tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
-	{
-		if (pset.sversion >= 110000)
-		{
-			appendPQExpBuffer(&buf, ",\n  CASE WHEN a.attnum <= (SELECT i.indnkeyatts FROM pg_catalog.pg_index i WHERE i.indexrelid = '%s') THEN '%s' ELSE '%s' END AS is_key",
-							  oid,
-							  gettext_noop("yes"),
-							  gettext_noop("no"));
-			isindexkey_col = cols++;
-		}
-		appendPQExpBufferStr(&buf, ",\n  pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef");
-		indexdef_col = cols++;
-	}
-	/* FDW options for foreign table column, only for 9.2 or later */
-	if (tableinfo.relkind == RELKIND_FOREIGN_TABLE && pset.sversion >= 90200)
+	switch ((RelKind) tableinfo.relkind)
 	{
-		appendPQExpBufferStr(&buf, ",\n  CASE WHEN attfdwoptions IS NULL THEN '' ELSE "
-							 "  '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)  FROM "
-							 "  pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
-		fdwopts_col = cols++;
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			if (pset.sversion >= 110000)
+			{
+				appendPQExpBuffer(&buf, ",\n  CASE WHEN a.attnum <= (SELECT i.indnkeyatts FROM pg_catalog.pg_index i WHERE i.indexrelid = '%s') THEN '%s' ELSE '%s' END AS is_key",
+								  oid,
+								  gettext_noop("yes"),
+								  gettext_noop("no"));
+				isindexkey_col = cols++;
+			}
+			appendPQExpBufferStr(&buf, ",\n  pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef");
+			indexdef_col = cols++;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			/* FDW options for foreign table column, only for 9.2 or later */
+			if (pset.sversion >= 90200)
+			{
+				appendPQExpBufferStr(&buf, ",\n  CASE WHEN attfdwoptions IS NULL THEN '' ELSE "
+									 "  '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)  FROM "
+									 "  pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
+				fdwopts_col = cols++;
+			}
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_MATVIEW:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
+
 	if (verbose)
 	{
 		appendPQExpBufferStr(&buf, ",\n  a.attstorage");
 		attstorage_col = cols++;
 
 		/* stats target, if relevant to relkind */
-		if (tableinfo.relkind == RELKIND_RELATION ||
-			tableinfo.relkind == RELKIND_INDEX ||
-			tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
-			tableinfo.relkind == RELKIND_MATVIEW ||
-			tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
-			tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
+		switch ((RelKind) tableinfo.relkind)
 		{
-			appendPQExpBufferStr(&buf, ",\n  CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget");
-			attstattarget_col = cols++;
+			case RELKIND_RELATION:
+			case RELKIND_INDEX:
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_MATVIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_PARTITIONED_TABLE:
+				appendPQExpBufferStr(&buf, ",\n  CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget");
+				attstattarget_col = cols++;
+				break;
+			case RELKIND_SEQUENCE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_VIEW:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 
 		/*
 		 * In 9.0+, we have column comments for: relations, views, composite
 		 * types, and foreign tables (cf. CommentObject() in comment.c).
 		 */
-		if (tableinfo.relkind == RELKIND_RELATION ||
-			tableinfo.relkind == RELKIND_VIEW ||
-			tableinfo.relkind == RELKIND_MATVIEW ||
-			tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
-			tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
-			tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
+		switch ((RelKind) tableinfo.relkind)
 		{
-			appendPQExpBufferStr(&buf, ",\n  pg_catalog.col_description(a.attrelid, a.attnum)");
-			attdescr_col = cols++;
+			case RELKIND_RELATION:
+			case RELKIND_VIEW:
+			case RELKIND_MATVIEW:
+			case RELKIND_FOREIGN_TABLE:
+			case RELKIND_COMPOSITE_TYPE:
+			case RELKIND_PARTITIONED_TABLE:
+				appendPQExpBufferStr(&buf, ",\n  pg_catalog.col_description(a.attrelid, a.attnum)");
+				attdescr_col = cols++;
+				break;
+			case RELKIND_PARTITIONED_INDEX:
+			case RELKIND_SEQUENCE:
+			case RELKIND_INDEX:
+			case RELKIND_TOASTVALUE:
+			case RELKIND_NULL:
+			default:
+				break;
 		}
 	}
 
@@ -1926,7 +1973,7 @@ describeOneTableDetails(const char *schemaname,
 	numrows = PQntuples(res);
 
 	/* Make title */
-	switch (tableinfo.relkind)
+	switch ((RelKind) tableinfo.relkind)
 	{
 		case RELKIND_RELATION:
 			if (tableinfo.relpersistence == 'u')
@@ -1964,11 +2011,6 @@ describeOneTableDetails(const char *schemaname,
 				printfPQExpBuffer(&title, _("Partitioned index \"%s.%s\""),
 								  schemaname, relationname);
 			break;
-		case 's':
-			/* not used as of 8.2, but keep it for backwards compatibility */
-			printfPQExpBuffer(&title, _("Special relation \"%s.%s\""),
-							  schemaname, relationname);
-			break;
 		case RELKIND_TOASTVALUE:
 			printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""),
 							  schemaname, relationname);
@@ -1989,10 +2031,23 @@ describeOneTableDetails(const char *schemaname,
 				printfPQExpBuffer(&title, _("Partitioned table \"%s.%s\""),
 								  schemaname, relationname);
 			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_NULL:
 		default:
-			/* untranslated unknown relkind */
-			printfPQExpBuffer(&title, "?%c? \"%s.%s\"",
-							  tableinfo.relkind, schemaname, relationname);
+
+			/*
+			 * 's' is not used as of 8.2, but we keep it for backwards
+			 * compatibility. We cannot handle 's' as a case value without
+			 * adding it to enum RelKind, but that would trigger warnings and
+			 * errors elsewhere.  Handle it here, instead.
+			 */
+			if ((RelKind) tableinfo.relkind == 's')
+				printfPQExpBuffer(&title, _("Special relation \"%s.%s\""),
+								  schemaname, relationname);
+			else
+				/* untranslated unknown relkind */
+				printfPQExpBuffer(&title, "?%c? \"%s.%s\"",
+								  tableinfo.relkind, schemaname, relationname);
 			break;
 	}
 
@@ -2150,742 +2205,806 @@ describeOneTableDetails(const char *schemaname,
 		PQclear(result);
 	}
 
-	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
+	switch ((RelKind) tableinfo.relkind)
 	{
-		/* Footer information for a partitioned table (partitioning parent) */
-		PGresult   *result;
-
-		printfPQExpBuffer(&buf,
-						  "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);",
-						  oid);
-		result = PSQLexec(buf.data);
-		if (!result)
-			goto error_return;
+		case RELKIND_PARTITIONED_TABLE:
+			{
+				/*
+				 * Footer information for a partitioned table (partitioning
+				 * parent)
+				 */
+				PGresult   *result;
 
-		if (PQntuples(result) == 1)
-		{
-			char	   *partkeydef = PQgetvalue(result, 0, 0);
+				printfPQExpBuffer(&buf,
+								  "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);",
+								  oid);
+				result = PSQLexec(buf.data);
+				if (!result)
+					goto error_return;
 
-			printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef);
-			printTableAddFooter(&cont, tmpbuf.data);
-		}
-		PQclear(result);
-	}
+				if (PQntuples(result) == 1)
+				{
+					char	   *partkeydef = PQgetvalue(result, 0, 0);
 
-	if (tableinfo.relkind == RELKIND_TOASTVALUE)
-	{
-		/* For a TOAST table, print name of owning table */
-		PGresult   *result;
+					printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef);
+					printTableAddFooter(&cont, tmpbuf.data);
+				}
+				PQclear(result);
+			}
+			break;
 
-		printfPQExpBuffer(&buf,
-						  "SELECT n.nspname, c.relname\n"
-						  "FROM pg_catalog.pg_class c"
-						  " JOIN pg_catalog.pg_namespace n"
-						  " ON n.oid = c.relnamespace\n"
-						  "WHERE reltoastrelid = '%s';", oid);
-		result = PSQLexec(buf.data);
-		if (!result)
-			goto error_return;
+		case RELKIND_TOASTVALUE:
+			{
+				/* For a TOAST table, print name of owning table */
+				PGresult   *result;
 
-		if (PQntuples(result) == 1)
-		{
-			char	   *schemaname = PQgetvalue(result, 0, 0);
-			char	   *relname = PQgetvalue(result, 0, 1);
+				printfPQExpBuffer(&buf,
+								  "SELECT n.nspname, c.relname\n"
+								  "FROM pg_catalog.pg_class c"
+								  " JOIN pg_catalog.pg_namespace n"
+								  " ON n.oid = c.relnamespace\n"
+								  "WHERE reltoastrelid = '%s';", oid);
+				result = PSQLexec(buf.data);
+				if (!result)
+					goto error_return;
+
+				if (PQntuples(result) == 1)
+				{
+					char	   *schemaname = PQgetvalue(result, 0, 0);
+					char	   *relname = PQgetvalue(result, 0, 1);
 
-			printfPQExpBuffer(&tmpbuf, _("Owning table: \"%s.%s\""),
-							  schemaname, relname);
-			printTableAddFooter(&cont, tmpbuf.data);
-		}
-		PQclear(result);
+					printfPQExpBuffer(&tmpbuf, _("Owning table: \"%s.%s\""),
+									  schemaname, relname);
+					printTableAddFooter(&cont, tmpbuf.data);
+				}
+				PQclear(result);
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_MATVIEW:
+		case RELKIND_RELATION:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
-	if (tableinfo.relkind == RELKIND_INDEX ||
-		tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
+	switch ((RelKind) tableinfo.relkind)
 	{
-		/* Footer information about an index */
-		PGresult   *result;
-
-		printfPQExpBuffer(&buf,
-						  "SELECT i.indisunique, i.indisprimary, i.indisclustered, ");
-		if (pset.sversion >= 80200)
-			appendPQExpBufferStr(&buf, "i.indisvalid,\n");
-		else
-			appendPQExpBufferStr(&buf, "true AS indisvalid,\n");
-		if (pset.sversion >= 90000)
-			appendPQExpBufferStr(&buf,
-								 "  (NOT i.indimmediate) AND "
-								 "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
-								 "WHERE conrelid = i.indrelid AND "
-								 "conindid = i.indexrelid AND "
-								 "contype IN ('p','u','x') AND "
-								 "condeferrable) AS condeferrable,\n"
-								 "  (NOT i.indimmediate) AND "
-								 "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
-								 "WHERE conrelid = i.indrelid AND "
-								 "conindid = i.indexrelid AND "
-								 "contype IN ('p','u','x') AND "
-								 "condeferred) AS condeferred,\n");
-		else
-			appendPQExpBufferStr(&buf,
-								 "  false AS condeferrable, false AS condeferred,\n");
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			{
+				/* Footer information about an index */
+				PGresult   *result;
 
-		if (pset.sversion >= 90400)
-			appendPQExpBufferStr(&buf, "i.indisreplident,\n");
-		else
-			appendPQExpBufferStr(&buf, "false AS indisreplident,\n");
+				printfPQExpBuffer(&buf,
+								  "SELECT i.indisunique, i.indisprimary, i.indisclustered, ");
+				if (pset.sversion >= 80200)
+					appendPQExpBufferStr(&buf, "i.indisvalid,\n");
+				else
+					appendPQExpBufferStr(&buf, "true AS indisvalid,\n");
+				if (pset.sversion >= 90000)
+					appendPQExpBufferStr(&buf,
+										 "  (NOT i.indimmediate) AND "
+										 "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
+										 "WHERE conrelid = i.indrelid AND "
+										 "conindid = i.indexrelid AND "
+										 "contype IN ('p','u','x') AND "
+										 "condeferrable) AS condeferrable,\n"
+										 "  (NOT i.indimmediate) AND "
+										 "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
+										 "WHERE conrelid = i.indrelid AND "
+										 "conindid = i.indexrelid AND "
+										 "contype IN ('p','u','x') AND "
+										 "condeferred) AS condeferred,\n");
+				else
+					appendPQExpBufferStr(&buf,
+										 "  false AS condeferrable, false AS condeferred,\n");
 
-		appendPQExpBuffer(&buf, "  a.amname, c2.relname, "
-						  "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n"
-						  "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n"
-						  "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n"
-						  "AND i.indrelid = c2.oid;",
-						  oid);
+				if (pset.sversion >= 90400)
+					appendPQExpBufferStr(&buf, "i.indisreplident,\n");
+				else
+					appendPQExpBufferStr(&buf, "false AS indisreplident,\n");
 
-		result = PSQLexec(buf.data);
-		if (!result)
-			goto error_return;
-		else if (PQntuples(result) != 1)
-		{
-			PQclear(result);
-			goto error_return;
-		}
-		else
-		{
-			char	   *indisunique = PQgetvalue(result, 0, 0);
-			char	   *indisprimary = PQgetvalue(result, 0, 1);
-			char	   *indisclustered = PQgetvalue(result, 0, 2);
-			char	   *indisvalid = PQgetvalue(result, 0, 3);
-			char	   *deferrable = PQgetvalue(result, 0, 4);
-			char	   *deferred = PQgetvalue(result, 0, 5);
-			char	   *indisreplident = PQgetvalue(result, 0, 6);
-			char	   *indamname = PQgetvalue(result, 0, 7);
-			char	   *indtable = PQgetvalue(result, 0, 8);
-			char	   *indpred = PQgetvalue(result, 0, 9);
-
-			if (strcmp(indisprimary, "t") == 0)
-				printfPQExpBuffer(&tmpbuf, _("primary key, "));
-			else if (strcmp(indisunique, "t") == 0)
-				printfPQExpBuffer(&tmpbuf, _("unique, "));
-			else
-				resetPQExpBuffer(&tmpbuf);
-			appendPQExpBuffer(&tmpbuf, "%s, ", indamname);
+				appendPQExpBuffer(&buf, "  a.amname, c2.relname, "
+								  "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n"
+								  "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n"
+								  "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n"
+								  "AND i.indrelid = c2.oid;",
+								  oid);
 
-			/* we assume here that index and table are in same schema */
-			appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""),
-							  schemaname, indtable);
+				result = PSQLexec(buf.data);
+				if (!result)
+					goto error_return;
+				else if (PQntuples(result) != 1)
+				{
+					PQclear(result);
+					goto error_return;
+				}
+				else
+				{
+					char	   *indisunique = PQgetvalue(result, 0, 0);
+					char	   *indisprimary = PQgetvalue(result, 0, 1);
+					char	   *indisclustered = PQgetvalue(result, 0, 2);
+					char	   *indisvalid = PQgetvalue(result, 0, 3);
+					char	   *deferrable = PQgetvalue(result, 0, 4);
+					char	   *deferred = PQgetvalue(result, 0, 5);
+					char	   *indisreplident = PQgetvalue(result, 0, 6);
+					char	   *indamname = PQgetvalue(result, 0, 7);
+					char	   *indtable = PQgetvalue(result, 0, 8);
+					char	   *indpred = PQgetvalue(result, 0, 9);
+
+					if (strcmp(indisprimary, "t") == 0)
+						printfPQExpBuffer(&tmpbuf, _("primary key, "));
+					else if (strcmp(indisunique, "t") == 0)
+						printfPQExpBuffer(&tmpbuf, _("unique, "));
+					else
+						resetPQExpBuffer(&tmpbuf);
+					appendPQExpBuffer(&tmpbuf, "%s, ", indamname);
 
-			if (strlen(indpred))
-				appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred);
+					/* we assume here that index and table are in same schema */
+					appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""),
+									  schemaname, indtable);
 
-			if (strcmp(indisclustered, "t") == 0)
-				appendPQExpBufferStr(&tmpbuf, _(", clustered"));
+					if (strlen(indpred))
+						appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred);
 
-			if (strcmp(indisvalid, "t") != 0)
-				appendPQExpBufferStr(&tmpbuf, _(", invalid"));
+					if (strcmp(indisclustered, "t") == 0)
+						appendPQExpBufferStr(&tmpbuf, _(", clustered"));
 
-			if (strcmp(deferrable, "t") == 0)
-				appendPQExpBufferStr(&tmpbuf, _(", deferrable"));
+					if (strcmp(indisvalid, "t") != 0)
+						appendPQExpBufferStr(&tmpbuf, _(", invalid"));
 
-			if (strcmp(deferred, "t") == 0)
-				appendPQExpBufferStr(&tmpbuf, _(", initially deferred"));
+					if (strcmp(deferrable, "t") == 0)
+						appendPQExpBufferStr(&tmpbuf, _(", deferrable"));
 
-			if (strcmp(indisreplident, "t") == 0)
-				appendPQExpBufferStr(&tmpbuf, _(", replica identity"));
+					if (strcmp(deferred, "t") == 0)
+						appendPQExpBufferStr(&tmpbuf, _(", initially deferred"));
 
-			printTableAddFooter(&cont, tmpbuf.data);
+					if (strcmp(indisreplident, "t") == 0)
+						appendPQExpBufferStr(&tmpbuf, _(", replica identity"));
 
-			/*
-			 * If it's a partitioned index, we'll print the tablespace below
-			 */
-			if (tableinfo.relkind == RELKIND_INDEX)
-				add_tablespace_footer(&cont, tableinfo.relkind,
-									  tableinfo.tablespace, true);
-		}
+					printTableAddFooter(&cont, tmpbuf.data);
 
-		PQclear(result);
-	}
-	/* If you add relkinds here, see also "Finish printing..." stanza below */
-	else if (tableinfo.relkind == RELKIND_RELATION ||
-			 tableinfo.relkind == RELKIND_MATVIEW ||
-			 tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
-			 tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
-			 tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
-			 tableinfo.relkind == RELKIND_TOASTVALUE)
-	{
-		/* Footer information about a table */
-		PGresult   *result = NULL;
-		int			tuples = 0;
+					/*
+					 * If it's a partitioned index, we'll print the tablespace
+					 * below
+					 */
+					if (tableinfo.relkind == RELKIND_INDEX)
+						add_tablespace_footer(&cont, tableinfo.relkind,
+											  tableinfo.tablespace, true);
+				}
 
-		/* print indexes */
-		if (tableinfo.hasindex)
-		{
-			printfPQExpBuffer(&buf,
-							  "SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, ");
-			if (pset.sversion >= 80200)
-				appendPQExpBufferStr(&buf, "i.indisvalid, ");
-			else
-				appendPQExpBufferStr(&buf, "true as indisvalid, ");
-			appendPQExpBufferStr(&buf, "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n  ");
-			if (pset.sversion >= 90000)
-				appendPQExpBufferStr(&buf,
-									 "pg_catalog.pg_get_constraintdef(con.oid, true), "
-									 "contype, condeferrable, condeferred");
-			else
-				appendPQExpBufferStr(&buf,
-									 "null AS constraintdef, null AS contype, "
-									 "false AS condeferrable, false AS condeferred");
-			if (pset.sversion >= 90400)
-				appendPQExpBufferStr(&buf, ", i.indisreplident");
-			else
-				appendPQExpBufferStr(&buf, ", false AS indisreplident");
-			if (pset.sversion >= 80000)
-				appendPQExpBufferStr(&buf, ", c2.reltablespace");
-			appendPQExpBufferStr(&buf,
-								 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n");
-			if (pset.sversion >= 90000)
-				appendPQExpBufferStr(&buf,
-									 "  LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n");
-			appendPQExpBuffer(&buf,
-							  "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
-							  "ORDER BY i.indisprimary DESC, c2.relname;",
-							  oid);
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
+				PQclear(result);
+			}
+			break;
 
-			if (tuples > 0)
+			/*
+			 * If you add relkinds here, see also "Finish printing..." stanza
+			 * below
+			 */
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_TOASTVALUE:
 			{
-				printTableAddFooter(&cont, _("Indexes:"));
-				for (i = 0; i < tuples; i++)
-				{
-					/* untranslated index name */
-					printfPQExpBuffer(&buf, "    \"%s\"",
-									  PQgetvalue(result, i, 0));
+				/* Footer information about a table */
+				PGresult   *result = NULL;
+				int			tuples = 0;
 
-					/* If exclusion constraint, print the constraintdef */
-					if (strcmp(PQgetvalue(result, i, 7), "x") == 0)
-					{
-						appendPQExpBuffer(&buf, " %s",
-										  PQgetvalue(result, i, 6));
-					}
+				/* print indexes */
+				if (tableinfo.hasindex)
+				{
+					printfPQExpBuffer(&buf,
+									  "SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, ");
+					if (pset.sversion >= 80200)
+						appendPQExpBufferStr(&buf, "i.indisvalid, ");
 					else
-					{
-						const char *indexdef;
-						const char *usingpos;
+						appendPQExpBufferStr(&buf, "true as indisvalid, ");
+					appendPQExpBufferStr(&buf, "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n  ");
+					if (pset.sversion >= 90000)
+						appendPQExpBufferStr(&buf,
+											 "pg_catalog.pg_get_constraintdef(con.oid, true), "
+											 "contype, condeferrable, condeferred");
+					else
+						appendPQExpBufferStr(&buf,
+											 "null AS constraintdef, null AS contype, "
+											 "false AS condeferrable, false AS condeferred");
+					if (pset.sversion >= 90400)
+						appendPQExpBufferStr(&buf, ", i.indisreplident");
+					else
+						appendPQExpBufferStr(&buf, ", false AS indisreplident");
+					if (pset.sversion >= 80000)
+						appendPQExpBufferStr(&buf, ", c2.reltablespace");
+					appendPQExpBufferStr(&buf,
+										 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n");
+					if (pset.sversion >= 90000)
+						appendPQExpBufferStr(&buf,
+											 "  LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n");
+					appendPQExpBuffer(&buf,
+									  "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
+									  "ORDER BY i.indisprimary DESC, c2.relname;",
+									  oid);
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-						/* Label as primary key or unique (but not both) */
-						if (strcmp(PQgetvalue(result, i, 1), "t") == 0)
-							appendPQExpBufferStr(&buf, " PRIMARY KEY,");
-						else if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
+					if (tuples > 0)
+					{
+						printTableAddFooter(&cont, _("Indexes:"));
+						for (i = 0; i < tuples; i++)
 						{
-							if (strcmp(PQgetvalue(result, i, 7), "u") == 0)
-								appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,");
+							/* untranslated index name */
+							printfPQExpBuffer(&buf, "    \"%s\"",
+											  PQgetvalue(result, i, 0));
+
+							/*
+							 * If exclusion constraint, print the
+							 * constraintdef
+							 */
+							if (strcmp(PQgetvalue(result, i, 7), "x") == 0)
+							{
+								appendPQExpBuffer(&buf, " %s",
+												  PQgetvalue(result, i, 6));
+							}
 							else
-								appendPQExpBufferStr(&buf, " UNIQUE,");
-						}
+							{
+								const char *indexdef;
+								const char *usingpos;
+
+								/*
+								 * Label as primary key or unique (but not
+								 * both)
+								 */
+								if (strcmp(PQgetvalue(result, i, 1), "t") == 0)
+									appendPQExpBufferStr(&buf, " PRIMARY KEY,");
+								else if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
+								{
+									if (strcmp(PQgetvalue(result, i, 7), "u") == 0)
+										appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,");
+									else
+										appendPQExpBufferStr(&buf, " UNIQUE,");
+								}
+
+								/* Everything after "USING" is echoed verbatim */
+								indexdef = PQgetvalue(result, i, 5);
+								usingpos = strstr(indexdef, " USING ");
+								if (usingpos)
+									indexdef = usingpos + 7;
+								appendPQExpBuffer(&buf, " %s", indexdef);
+
+								/* Need these for deferrable PK/UNIQUE indexes */
+								if (strcmp(PQgetvalue(result, i, 8), "t") == 0)
+									appendPQExpBufferStr(&buf, " DEFERRABLE");
+
+								if (strcmp(PQgetvalue(result, i, 9), "t") == 0)
+									appendPQExpBufferStr(&buf, " INITIALLY DEFERRED");
+							}
 
-						/* Everything after "USING" is echoed verbatim */
-						indexdef = PQgetvalue(result, i, 5);
-						usingpos = strstr(indexdef, " USING ");
-						if (usingpos)
-							indexdef = usingpos + 7;
-						appendPQExpBuffer(&buf, " %s", indexdef);
+							/* Add these for all cases */
+							if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
+								appendPQExpBufferStr(&buf, " CLUSTER");
 
-						/* Need these for deferrable PK/UNIQUE indexes */
-						if (strcmp(PQgetvalue(result, i, 8), "t") == 0)
-							appendPQExpBufferStr(&buf, " DEFERRABLE");
+							if (strcmp(PQgetvalue(result, i, 4), "t") != 0)
+								appendPQExpBufferStr(&buf, " INVALID");
 
-						if (strcmp(PQgetvalue(result, i, 9), "t") == 0)
-							appendPQExpBufferStr(&buf, " INITIALLY DEFERRED");
-					}
+							if (strcmp(PQgetvalue(result, i, 10), "t") == 0)
+								appendPQExpBufferStr(&buf, " REPLICA IDENTITY");
 
-					/* Add these for all cases */
-					if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
-						appendPQExpBufferStr(&buf, " CLUSTER");
+							printTableAddFooter(&cont, buf.data);
 
-					if (strcmp(PQgetvalue(result, i, 4), "t") != 0)
-						appendPQExpBufferStr(&buf, " INVALID");
+							/* Print tablespace of the index on the same line */
+							if (pset.sversion >= 80000)
+								add_tablespace_footer(&cont, RELKIND_INDEX,
+													  atooid(PQgetvalue(result, i, 11)),
+													  false);
+						}
+					}
+					PQclear(result);
+				}
 
-					if (strcmp(PQgetvalue(result, i, 10), "t") == 0)
-						appendPQExpBufferStr(&buf, " REPLICA IDENTITY");
+				/* print table (and column) check constraints */
+				if (tableinfo.checks)
+				{
+					printfPQExpBuffer(&buf,
+									  "SELECT r.conname, "
+									  "pg_catalog.pg_get_constraintdef(r.oid, true)\n"
+									  "FROM pg_catalog.pg_constraint r\n"
+									  "WHERE r.conrelid = '%s' AND r.contype = 'c'\n"
+									  "ORDER BY 1;",
+									  oid);
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-					printTableAddFooter(&cont, buf.data);
+					if (tuples > 0)
+					{
+						printTableAddFooter(&cont, _("Check constraints:"));
+						for (i = 0; i < tuples; i++)
+						{
+							/* untranslated constraint name and def */
+							printfPQExpBuffer(&buf, "    \"%s\" %s",
+											  PQgetvalue(result, i, 0),
+											  PQgetvalue(result, i, 1));
 
-					/* Print tablespace of the index on the same line */
-					if (pset.sversion >= 80000)
-						add_tablespace_footer(&cont, RELKIND_INDEX,
-											  atooid(PQgetvalue(result, i, 11)),
-											  false);
+							printTableAddFooter(&cont, buf.data);
+						}
+					}
+					PQclear(result);
 				}
-			}
-			PQclear(result);
-		}
-
-		/* print table (and column) check constraints */
-		if (tableinfo.checks)
-		{
-			printfPQExpBuffer(&buf,
-							  "SELECT r.conname, "
-							  "pg_catalog.pg_get_constraintdef(r.oid, true)\n"
-							  "FROM pg_catalog.pg_constraint r\n"
-							  "WHERE r.conrelid = '%s' AND r.contype = 'c'\n"
-							  "ORDER BY 1;",
-							  oid);
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
 
-			if (tuples > 0)
-			{
-				printTableAddFooter(&cont, _("Check constraints:"));
-				for (i = 0; i < tuples; i++)
+				/*
+				 * Print foreign-key constraints (there are none if no
+				 * triggers, except if the table is partitioned, in which case
+				 * the triggers appear in the partitions)
+				 */
+				if (tableinfo.hastriggers ||
+					tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 				{
-					/* untranslated constraint name and def */
-					printfPQExpBuffer(&buf, "    \"%s\" %s",
-									  PQgetvalue(result, i, 0),
-									  PQgetvalue(result, i, 1));
-
-					printTableAddFooter(&cont, buf.data);
-				}
-			}
-			PQclear(result);
-		}
+					if (pset.sversion >= 120000 &&
+						(tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE))
+					{
+						/*
+						 * Put the constraints defined in this table first,
+						 * followed by the constraints defined in ancestor
+						 * partitioned tables.
+						 */
+						printfPQExpBuffer(&buf,
+										  "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n"
+										  "       conname,\n"
+										  "       pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n"
+										  "       conrelid::pg_catalog.regclass AS ontable\n"
+										  "  FROM pg_catalog.pg_constraint,\n"
+										  "       pg_catalog.pg_partition_ancestors('%s')\n"
+										  " WHERE conrelid = relid AND contype = 'f' AND conparentid = 0\n"
+										  "ORDER BY sametable DESC, conname;",
+										  oid, oid);
+					}
+					else
+					{
+						printfPQExpBuffer(&buf,
+										  "SELECT true as sametable, conname,\n"
+										  "  pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n"
+										  "  conrelid::pg_catalog.regclass AS ontable\n"
+										  "FROM pg_catalog.pg_constraint r\n"
+										  "WHERE r.conrelid = '%s' AND r.contype = 'f'\n",
+										  oid);
+
+						if (pset.sversion >= 120000)
+							appendPQExpBufferStr(&buf, "     AND conparentid = 0\n");
+						appendPQExpBufferStr(&buf, "ORDER BY conname");
+					}
 
-		/*
-		 * Print foreign-key constraints (there are none if no triggers,
-		 * except if the table is partitioned, in which case the triggers
-		 * appear in the partitions)
-		 */
-		if (tableinfo.hastriggers ||
-			tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
-		{
-			if (pset.sversion >= 120000 &&
-				(tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE))
-			{
-				/*
-				 * Put the constraints defined in this table first, followed
-				 * by the constraints defined in ancestor partitioned tables.
-				 */
-				printfPQExpBuffer(&buf,
-								  "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n"
-								  "       conname,\n"
-								  "       pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n"
-								  "       conrelid::pg_catalog.regclass AS ontable\n"
-								  "  FROM pg_catalog.pg_constraint,\n"
-								  "       pg_catalog.pg_partition_ancestors('%s')\n"
-								  " WHERE conrelid = relid AND contype = 'f' AND conparentid = 0\n"
-								  "ORDER BY sametable DESC, conname;",
-								  oid, oid);
-			}
-			else
-			{
-				printfPQExpBuffer(&buf,
-								  "SELECT true as sametable, conname,\n"
-								  "  pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n"
-								  "  conrelid::pg_catalog.regclass AS ontable\n"
-								  "FROM pg_catalog.pg_constraint r\n"
-								  "WHERE r.conrelid = '%s' AND r.contype = 'f'\n",
-								  oid);
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-				if (pset.sversion >= 120000)
-					appendPQExpBufferStr(&buf, "     AND conparentid = 0\n");
-				appendPQExpBufferStr(&buf, "ORDER BY conname");
-			}
+					if (tuples > 0)
+					{
+						int			i_sametable = PQfnumber(result, "sametable"),
+									i_conname = PQfnumber(result, "conname"),
+									i_condef = PQfnumber(result, "condef"),
+									i_ontable = PQfnumber(result, "ontable");
 
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
+						printTableAddFooter(&cont, _("Foreign-key constraints:"));
+						for (i = 0; i < tuples; i++)
+						{
+							/*
+							 * Print untranslated constraint name and
+							 * definition. Use a "TABLE tab" prefix when the
+							 * constraint is defined in a parent partitioned
+							 * table.
+							 */
+							if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0)
+								printfPQExpBuffer(&buf, "    TABLE \"%s\" CONSTRAINT \"%s\" %s",
+												  PQgetvalue(result, i, i_ontable),
+												  PQgetvalue(result, i, i_conname),
+												  PQgetvalue(result, i, i_condef));
+							else
+								printfPQExpBuffer(&buf, "    \"%s\" %s",
+												  PQgetvalue(result, i, i_conname),
+												  PQgetvalue(result, i, i_condef));
 
-			if (tuples > 0)
-			{
-				int			i_sametable = PQfnumber(result, "sametable"),
-							i_conname = PQfnumber(result, "conname"),
-							i_condef = PQfnumber(result, "condef"),
-							i_ontable = PQfnumber(result, "ontable");
+							printTableAddFooter(&cont, buf.data);
+						}
+					}
+					PQclear(result);
+				}
 
-				printTableAddFooter(&cont, _("Foreign-key constraints:"));
-				for (i = 0; i < tuples; i++)
+				/* print incoming foreign-key references */
+				if (tableinfo.hastriggers ||
+					tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 				{
-					/*
-					 * Print untranslated constraint name and definition. Use
-					 * a "TABLE tab" prefix when the constraint is defined in
-					 * a parent partitioned table.
-					 */
-					if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0)
-						printfPQExpBuffer(&buf, "    TABLE \"%s\" CONSTRAINT \"%s\" %s",
-										  PQgetvalue(result, i, i_ontable),
-										  PQgetvalue(result, i, i_conname),
-										  PQgetvalue(result, i, i_condef));
+					if (pset.sversion >= 120000)
+					{
+						printfPQExpBuffer(&buf,
+										  "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
+										  "       pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
+										  "  FROM pg_catalog.pg_constraint c\n"
+										  " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n"
+										  "                     UNION ALL VALUES ('%s'::pg_catalog.regclass))\n"
+										  "       AND contype = 'f' AND conparentid = 0\n"
+										  "ORDER BY conname;",
+										  oid, oid);
+					}
 					else
-						printfPQExpBuffer(&buf, "    \"%s\" %s",
-										  PQgetvalue(result, i, i_conname),
-										  PQgetvalue(result, i, i_condef));
+					{
+						printfPQExpBuffer(&buf,
+										  "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
+										  "       pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
+										  "  FROM pg_catalog.pg_constraint\n"
+										  " WHERE confrelid = %s AND contype = 'f'\n"
+										  "ORDER BY conname;",
+										  oid);
+					}
 
-					printTableAddFooter(&cont, buf.data);
-				}
-			}
-			PQclear(result);
-		}
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-		/* print incoming foreign-key references */
-		if (tableinfo.hastriggers ||
-			tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
-		{
-			if (pset.sversion >= 120000)
-			{
-				printfPQExpBuffer(&buf,
-								  "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
-								  "       pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
-								  "  FROM pg_catalog.pg_constraint c\n"
-								  " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n"
-								  "                     UNION ALL VALUES ('%s'::pg_catalog.regclass))\n"
-								  "       AND contype = 'f' AND conparentid = 0\n"
-								  "ORDER BY conname;",
-								  oid, oid);
-			}
-			else
-			{
-				printfPQExpBuffer(&buf,
-								  "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
-								  "       pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
-								  "  FROM pg_catalog.pg_constraint\n"
-								  " WHERE confrelid = %s AND contype = 'f'\n"
-								  "ORDER BY conname;",
-								  oid);
-			}
+					if (tuples > 0)
+					{
+						int			i_conname = PQfnumber(result, "conname"),
+									i_ontable = PQfnumber(result, "ontable"),
+									i_condef = PQfnumber(result, "condef");
 
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
+						printTableAddFooter(&cont, _("Referenced by:"));
+						for (i = 0; i < tuples; i++)
+						{
+							printfPQExpBuffer(&buf, "    TABLE \"%s\" CONSTRAINT \"%s\" %s",
+											  PQgetvalue(result, i, i_ontable),
+											  PQgetvalue(result, i, i_conname),
+											  PQgetvalue(result, i, i_condef));
 
-			if (tuples > 0)
-			{
-				int			i_conname = PQfnumber(result, "conname"),
-							i_ontable = PQfnumber(result, "ontable"),
-							i_condef = PQfnumber(result, "condef");
+							printTableAddFooter(&cont, buf.data);
+						}
+					}
+					PQclear(result);
+				}
 
-				printTableAddFooter(&cont, _("Referenced by:"));
-				for (i = 0; i < tuples; i++)
+				/* print any row-level policies */
+				if (pset.sversion >= 90500)
 				{
-					printfPQExpBuffer(&buf, "    TABLE \"%s\" CONSTRAINT \"%s\" %s",
-									  PQgetvalue(result, i, i_ontable),
-									  PQgetvalue(result, i, i_conname),
-									  PQgetvalue(result, i, i_condef));
+					printfPQExpBuffer(&buf, "SELECT pol.polname,");
+					if (pset.sversion >= 100000)
+						appendPQExpBufferStr(&buf,
+											 " pol.polpermissive,\n");
+					else
+						appendPQExpBufferStr(&buf,
+											 " 't' as polpermissive,\n");
+					appendPQExpBuffer(&buf,
+									  "  CASE WHEN pol.polroles = '{0}' THEN NULL ELSE pg_catalog.array_to_string(array(select rolname from pg_catalog.pg_roles where oid = any (pol.polroles) order by 1),',') END,\n"
+									  "  pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
+									  "  pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
+									  "  CASE pol.polcmd\n"
+									  "    WHEN 'r' THEN 'SELECT'\n"
+									  "    WHEN 'a' THEN 'INSERT'\n"
+									  "    WHEN 'w' THEN 'UPDATE'\n"
+									  "    WHEN 'd' THEN 'DELETE'\n"
+									  "    END AS cmd\n"
+									  "FROM pg_catalog.pg_policy pol\n"
+									  "WHERE pol.polrelid = '%s' ORDER BY 1;",
+									  oid);
+
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-					printTableAddFooter(&cont, buf.data);
-				}
-			}
-			PQclear(result);
-		}
+					/*
+					 * Handle cases where RLS is enabled and there are
+					 * policies, or there aren't policies, or RLS isn't
+					 * enabled but there are policies
+					 */
+					if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0)
+						printTableAddFooter(&cont, _("Policies:"));
 
-		/* print any row-level policies */
-		if (pset.sversion >= 90500)
-		{
-			printfPQExpBuffer(&buf, "SELECT pol.polname,");
-			if (pset.sversion >= 100000)
-				appendPQExpBufferStr(&buf,
-									 " pol.polpermissive,\n");
-			else
-				appendPQExpBufferStr(&buf,
-									 " 't' as polpermissive,\n");
-			appendPQExpBuffer(&buf,
-							  "  CASE WHEN pol.polroles = '{0}' THEN NULL ELSE pg_catalog.array_to_string(array(select rolname from pg_catalog.pg_roles where oid = any (pol.polroles) order by 1),',') END,\n"
-							  "  pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
-							  "  pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
-							  "  CASE pol.polcmd\n"
-							  "    WHEN 'r' THEN 'SELECT'\n"
-							  "    WHEN 'a' THEN 'INSERT'\n"
-							  "    WHEN 'w' THEN 'UPDATE'\n"
-							  "    WHEN 'd' THEN 'DELETE'\n"
-							  "    END AS cmd\n"
-							  "FROM pg_catalog.pg_policy pol\n"
-							  "WHERE pol.polrelid = '%s' ORDER BY 1;",
-							  oid);
+					if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0)
+						printTableAddFooter(&cont, _("Policies (forced row security enabled):"));
 
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
+					if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0)
+						printTableAddFooter(&cont, _("Policies (row security enabled): (none)"));
 
-			/*
-			 * Handle cases where RLS is enabled and there are policies, or
-			 * there aren't policies, or RLS isn't enabled but there are
-			 * policies
-			 */
-			if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0)
-				printTableAddFooter(&cont, _("Policies:"));
+					if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0)
+						printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)"));
 
-			if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0)
-				printTableAddFooter(&cont, _("Policies (forced row security enabled):"));
+					if (!tableinfo.rowsecurity && tuples > 0)
+						printTableAddFooter(&cont, _("Policies (row security disabled):"));
 
-			if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0)
-				printTableAddFooter(&cont, _("Policies (row security enabled): (none)"));
+					/* Might be an empty set - that's ok */
+					for (i = 0; i < tuples; i++)
+					{
+						printfPQExpBuffer(&buf, "    POLICY \"%s\"",
+										  PQgetvalue(result, i, 0));
 
-			if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0)
-				printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)"));
+						if (*(PQgetvalue(result, i, 1)) == 'f')
+							appendPQExpBufferStr(&buf, " AS RESTRICTIVE");
 
-			if (!tableinfo.rowsecurity && tuples > 0)
-				printTableAddFooter(&cont, _("Policies (row security disabled):"));
+						if (!PQgetisnull(result, i, 5))
+							appendPQExpBuffer(&buf, " FOR %s",
+											  PQgetvalue(result, i, 5));
 
-			/* Might be an empty set - that's ok */
-			for (i = 0; i < tuples; i++)
-			{
-				printfPQExpBuffer(&buf, "    POLICY \"%s\"",
-								  PQgetvalue(result, i, 0));
+						if (!PQgetisnull(result, i, 2))
+						{
+							appendPQExpBuffer(&buf, "\n      TO %s",
+											  PQgetvalue(result, i, 2));
+						}
 
-				if (*(PQgetvalue(result, i, 1)) == 'f')
-					appendPQExpBufferStr(&buf, " AS RESTRICTIVE");
+						if (!PQgetisnull(result, i, 3))
+							appendPQExpBuffer(&buf, "\n      USING (%s)",
+											  PQgetvalue(result, i, 3));
 
-				if (!PQgetisnull(result, i, 5))
-					appendPQExpBuffer(&buf, " FOR %s",
-									  PQgetvalue(result, i, 5));
+						if (!PQgetisnull(result, i, 4))
+							appendPQExpBuffer(&buf, "\n      WITH CHECK (%s)",
+											  PQgetvalue(result, i, 4));
 
-				if (!PQgetisnull(result, i, 2))
-				{
-					appendPQExpBuffer(&buf, "\n      TO %s",
-									  PQgetvalue(result, i, 2));
-				}
+						printTableAddFooter(&cont, buf.data);
 
-				if (!PQgetisnull(result, i, 3))
-					appendPQExpBuffer(&buf, "\n      USING (%s)",
-									  PQgetvalue(result, i, 3));
+					}
+					PQclear(result);
+				}
 
-				if (!PQgetisnull(result, i, 4))
-					appendPQExpBuffer(&buf, "\n      WITH CHECK (%s)",
-									  PQgetvalue(result, i, 4));
+				/* print any extended statistics */
+				if (pset.sversion >= 100000)
+				{
+					printfPQExpBuffer(&buf,
+									  "SELECT oid, "
+									  "stxrelid::pg_catalog.regclass, "
+									  "stxnamespace::pg_catalog.regnamespace AS nsp, "
+									  "stxname,\n"
+									  "  (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')\n"
+									  "   FROM pg_catalog.unnest(stxkeys) s(attnum)\n"
+									  "   JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n"
+									  "        a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n"
+									  "  'd' = any(stxkind) AS ndist_enabled,\n"
+									  "  'f' = any(stxkind) AS deps_enabled,\n"
+									  "  'm' = any(stxkind) AS mcv_enabled\n"
+									  "FROM pg_catalog.pg_statistic_ext stat "
+									  "WHERE stxrelid = '%s'\n"
+									  "ORDER BY 1;",
+									  oid);
+
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-				printTableAddFooter(&cont, buf.data);
+					if (tuples > 0)
+					{
+						printTableAddFooter(&cont, _("Statistics objects:"));
 
-			}
-			PQclear(result);
-		}
+						for (i = 0; i < tuples; i++)
+						{
+							bool		gotone = false;
 
-		/* print any extended statistics */
-		if (pset.sversion >= 100000)
-		{
-			printfPQExpBuffer(&buf,
-							  "SELECT oid, "
-							  "stxrelid::pg_catalog.regclass, "
-							  "stxnamespace::pg_catalog.regnamespace AS nsp, "
-							  "stxname,\n"
-							  "  (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')\n"
-							  "   FROM pg_catalog.unnest(stxkeys) s(attnum)\n"
-							  "   JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n"
-							  "        a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n"
-							  "  'd' = any(stxkind) AS ndist_enabled,\n"
-							  "  'f' = any(stxkind) AS deps_enabled,\n"
-							  "  'm' = any(stxkind) AS mcv_enabled\n"
-							  "FROM pg_catalog.pg_statistic_ext stat "
-							  "WHERE stxrelid = '%s'\n"
-							  "ORDER BY 1;",
-							  oid);
+							printfPQExpBuffer(&buf, "    ");
 
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
+							/*
+							 * statistics object name (qualified with
+							 * namespace)
+							 */
+							appendPQExpBuffer(&buf, "\"%s\".\"%s\" (",
+											  PQgetvalue(result, i, 2),
+											  PQgetvalue(result, i, 3));
 
-			if (tuples > 0)
-			{
-				printTableAddFooter(&cont, _("Statistics objects:"));
+							/* options */
+							if (strcmp(PQgetvalue(result, i, 5), "t") == 0)
+							{
+								appendPQExpBufferStr(&buf, "ndistinct");
+								gotone = true;
+							}
 
-				for (i = 0; i < tuples; i++)
-				{
-					bool		gotone = false;
+							if (strcmp(PQgetvalue(result, i, 6), "t") == 0)
+							{
+								appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
+								gotone = true;
+							}
 
-					printfPQExpBuffer(&buf, "    ");
+							if (strcmp(PQgetvalue(result, i, 7), "t") == 0)
+							{
+								appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : "");
+							}
 
-					/* statistics object name (qualified with namespace) */
-					appendPQExpBuffer(&buf, "\"%s\".\"%s\" (",
-									  PQgetvalue(result, i, 2),
-									  PQgetvalue(result, i, 3));
+							appendPQExpBuffer(&buf, ") ON %s FROM %s",
+											  PQgetvalue(result, i, 4),
+											  PQgetvalue(result, i, 1));
 
-					/* options */
-					if (strcmp(PQgetvalue(result, i, 5), "t") == 0)
-					{
-						appendPQExpBufferStr(&buf, "ndistinct");
-						gotone = true;
+							printTableAddFooter(&cont, buf.data);
+						}
 					}
+					PQclear(result);
+				}
 
-					if (strcmp(PQgetvalue(result, i, 6), "t") == 0)
+				/* print rules */
+				if (tableinfo.hasrules && tableinfo.relkind != RELKIND_MATVIEW)
+				{
+					if (pset.sversion >= 80300)
 					{
-						appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
-						gotone = true;
+						printfPQExpBuffer(&buf,
+										  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
+										  "ev_enabled\n"
+										  "FROM pg_catalog.pg_rewrite r\n"
+										  "WHERE r.ev_class = '%s' ORDER BY 1;",
+										  oid);
 					}
-
-					if (strcmp(PQgetvalue(result, i, 7), "t") == 0)
+					else
 					{
-						appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : "");
+						printfPQExpBuffer(&buf,
+										  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
+										  "'O' AS ev_enabled\n"
+										  "FROM pg_catalog.pg_rewrite r\n"
+										  "WHERE r.ev_class = '%s' ORDER BY 1;",
+										  oid);
 					}
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-					appendPQExpBuffer(&buf, ") ON %s FROM %s",
-									  PQgetvalue(result, i, 4),
-									  PQgetvalue(result, i, 1));
-
-					printTableAddFooter(&cont, buf.data);
-				}
-			}
-			PQclear(result);
-		}
-
-		/* print rules */
-		if (tableinfo.hasrules && tableinfo.relkind != RELKIND_MATVIEW)
-		{
-			if (pset.sversion >= 80300)
-			{
-				printfPQExpBuffer(&buf,
-								  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
-								  "ev_enabled\n"
-								  "FROM pg_catalog.pg_rewrite r\n"
-								  "WHERE r.ev_class = '%s' ORDER BY 1;",
-								  oid);
-			}
-			else
-			{
-				printfPQExpBuffer(&buf,
-								  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
-								  "'O' AS ev_enabled\n"
-								  "FROM pg_catalog.pg_rewrite r\n"
-								  "WHERE r.ev_class = '%s' ORDER BY 1;",
-								  oid);
-			}
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
-
-			if (tuples > 0)
-			{
-				bool		have_heading;
-				int			category;
-
-				for (category = 0; category < 4; category++)
-				{
-					have_heading = false;
-
-					for (i = 0; i < tuples; i++)
+					if (tuples > 0)
 					{
-						const char *ruledef;
-						bool		list_rule = false;
+						bool		have_heading;
+						int			category;
 
-						switch (category)
+						for (category = 0; category < 4; category++)
 						{
-							case 0:
-								if (*PQgetvalue(result, i, 2) == 'O')
-									list_rule = true;
-								break;
-							case 1:
-								if (*PQgetvalue(result, i, 2) == 'D')
-									list_rule = true;
-								break;
-							case 2:
-								if (*PQgetvalue(result, i, 2) == 'A')
-									list_rule = true;
-								break;
-							case 3:
-								if (*PQgetvalue(result, i, 2) == 'R')
-									list_rule = true;
-								break;
-						}
-						if (!list_rule)
-							continue;
+							have_heading = false;
 
-						if (!have_heading)
-						{
-							switch (category)
+							for (i = 0; i < tuples; i++)
 							{
-								case 0:
-									printfPQExpBuffer(&buf, _("Rules:"));
-									break;
-								case 1:
-									printfPQExpBuffer(&buf, _("Disabled rules:"));
-									break;
-								case 2:
-									printfPQExpBuffer(&buf, _("Rules firing always:"));
-									break;
-								case 3:
-									printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
-									break;
+								const char *ruledef;
+								bool		list_rule = false;
+
+								switch (category)
+								{
+									case 0:
+										if (*PQgetvalue(result, i, 2) == 'O')
+											list_rule = true;
+										break;
+									case 1:
+										if (*PQgetvalue(result, i, 2) == 'D')
+											list_rule = true;
+										break;
+									case 2:
+										if (*PQgetvalue(result, i, 2) == 'A')
+											list_rule = true;
+										break;
+									case 3:
+										if (*PQgetvalue(result, i, 2) == 'R')
+											list_rule = true;
+										break;
+								}
+								if (!list_rule)
+									continue;
+
+								if (!have_heading)
+								{
+									switch (category)
+									{
+										case 0:
+											printfPQExpBuffer(&buf, _("Rules:"));
+											break;
+										case 1:
+											printfPQExpBuffer(&buf, _("Disabled rules:"));
+											break;
+										case 2:
+											printfPQExpBuffer(&buf, _("Rules firing always:"));
+											break;
+										case 3:
+											printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
+											break;
+									}
+									printTableAddFooter(&cont, buf.data);
+									have_heading = true;
+								}
+
+								/*
+								 * Everything after "CREATE RULE" is echoed
+								 * verbatim
+								 */
+								ruledef = PQgetvalue(result, i, 1);
+								ruledef += 12;
+								printfPQExpBuffer(&buf, "    %s", ruledef);
+								printTableAddFooter(&cont, buf.data);
 							}
-							printTableAddFooter(&cont, buf.data);
-							have_heading = true;
 						}
-
-						/* Everything after "CREATE RULE" is echoed verbatim */
-						ruledef = PQgetvalue(result, i, 1);
-						ruledef += 12;
-						printfPQExpBuffer(&buf, "    %s", ruledef);
-						printTableAddFooter(&cont, buf.data);
 					}
+					PQclear(result);
 				}
-			}
-			PQclear(result);
-		}
 
-		/* print any publications */
-		if (pset.sversion >= 100000)
-		{
-			printfPQExpBuffer(&buf,
-							  "SELECT pubname\n"
-							  "FROM pg_catalog.pg_publication p\n"
-							  "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
-							  "WHERE pr.prrelid = '%s'\n"
-							  "UNION ALL\n"
-							  "SELECT pubname\n"
-							  "FROM pg_catalog.pg_publication p\n"
-							  "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
-							  "ORDER BY 1;",
-							  oid, oid);
-
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else
-				tuples = PQntuples(result);
+				/* print any publications */
+				if (pset.sversion >= 100000)
+				{
+					printfPQExpBuffer(&buf,
+									  "SELECT pubname\n"
+									  "FROM pg_catalog.pg_publication p\n"
+									  "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
+									  "WHERE pr.prrelid = '%s'\n"
+									  "UNION ALL\n"
+									  "SELECT pubname\n"
+									  "FROM pg_catalog.pg_publication p\n"
+									  "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
+									  "ORDER BY 1;",
+									  oid, oid);
+
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else
+						tuples = PQntuples(result);
 
-			if (tuples > 0)
-				printTableAddFooter(&cont, _("Publications:"));
+					if (tuples > 0)
+						printTableAddFooter(&cont, _("Publications:"));
 
-			/* Might be an empty set - that's ok */
-			for (i = 0; i < tuples; i++)
-			{
-				printfPQExpBuffer(&buf, "    \"%s\"",
-								  PQgetvalue(result, i, 0));
+					/* Might be an empty set - that's ok */
+					for (i = 0; i < tuples; i++)
+					{
+						printfPQExpBuffer(&buf, "    \"%s\"",
+										  PQgetvalue(result, i, 0));
 
-				printTableAddFooter(&cont, buf.data);
+						printTableAddFooter(&cont, buf.data);
+					}
+					PQclear(result);
+				}
 			}
-			PQclear(result);
-		}
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* Get view_def if table is a view or materialized view */
-	if ((tableinfo.relkind == RELKIND_VIEW ||
-		 tableinfo.relkind == RELKIND_MATVIEW) && verbose)
+	switch ((RelKind) tableinfo.relkind)
 	{
-		PGresult   *result;
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+			if (verbose)
+			{
+				PGresult   *result;
 
-		printfPQExpBuffer(&buf,
-						  "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);",
-						  oid);
-		result = PSQLexec(buf.data);
-		if (!result)
-			goto error_return;
+				printfPQExpBuffer(&buf,
+								  "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);",
+								  oid);
+				result = PSQLexec(buf.data);
+				if (!result)
+					goto error_return;
 
-		if (PQntuples(result) > 0)
-			view_def = pg_strdup(PQgetvalue(result, 0, 0));
+				if (PQntuples(result) > 0)
+					view_def = pg_strdup(PQgetvalue(result, 0, 0));
 
-		PQclear(result);
+				PQclear(result);
+			}
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_RELATION:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	if (view_def)
@@ -3086,224 +3205,235 @@ describeOneTableDetails(const char *schemaname,
 	/*
 	 * Finish printing the footer information about a table.
 	 */
-	if (tableinfo.relkind == RELKIND_RELATION ||
-		tableinfo.relkind == RELKIND_MATVIEW ||
-		tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
-		tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
-		tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
-		tableinfo.relkind == RELKIND_TOASTVALUE)
+	switch ((RelKind) tableinfo.relkind)
 	{
-		bool		is_partitioned;
-		PGresult   *result;
-		int			tuples;
-
-		/* simplify some repeated tests below */
-		is_partitioned = (tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
-						  tableinfo.relkind == RELKIND_PARTITIONED_INDEX);
-
-		/* print foreign server name */
-		if (tableinfo.relkind == RELKIND_FOREIGN_TABLE)
-		{
-			char	   *ftoptions;
-
-			/* Footer information about foreign table */
-			printfPQExpBuffer(&buf,
-							  "SELECT s.srvname,\n"
-							  "  pg_catalog.array_to_string(ARRAY(\n"
-							  "    SELECT pg_catalog.quote_ident(option_name)"
-							  " || ' ' || pg_catalog.quote_literal(option_value)\n"
-							  "    FROM pg_catalog.pg_options_to_table(ftoptions)),  ', ')\n"
-							  "FROM pg_catalog.pg_foreign_table f,\n"
-							  "     pg_catalog.pg_foreign_server s\n"
-							  "WHERE f.ftrelid = '%s' AND s.oid = f.ftserver;",
-							  oid);
-			result = PSQLexec(buf.data);
-			if (!result)
-				goto error_return;
-			else if (PQntuples(result) != 1)
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_TOASTVALUE:
 			{
-				PQclear(result);
-				goto error_return;
-			}
+				bool		is_partitioned;
+				PGresult   *result;
+				int			tuples;
 
-			/* Print server name */
-			printfPQExpBuffer(&buf, _("Server: %s"),
-							  PQgetvalue(result, 0, 0));
-			printTableAddFooter(&cont, buf.data);
+				/* simplify some repeated tests below */
+				is_partitioned = (tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
+								  tableinfo.relkind == RELKIND_PARTITIONED_INDEX);
 
-			/* Print per-table FDW options, if any */
-			ftoptions = PQgetvalue(result, 0, 1);
-			if (ftoptions && ftoptions[0] != '\0')
-			{
-				printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions);
-				printTableAddFooter(&cont, buf.data);
-			}
-			PQclear(result);
-		}
+				/* print foreign server name */
+				if (tableinfo.relkind == RELKIND_FOREIGN_TABLE)
+				{
+					char	   *ftoptions;
+
+					/* Footer information about foreign table */
+					printfPQExpBuffer(&buf,
+									  "SELECT s.srvname,\n"
+									  "  pg_catalog.array_to_string(ARRAY(\n"
+									  "    SELECT pg_catalog.quote_ident(option_name)"
+									  " || ' ' || pg_catalog.quote_literal(option_value)\n"
+									  "    FROM pg_catalog.pg_options_to_table(ftoptions)),  ', ')\n"
+									  "FROM pg_catalog.pg_foreign_table f,\n"
+									  "     pg_catalog.pg_foreign_server s\n"
+									  "WHERE f.ftrelid = '%s' AND s.oid = f.ftserver;",
+									  oid);
+					result = PSQLexec(buf.data);
+					if (!result)
+						goto error_return;
+					else if (PQntuples(result) != 1)
+					{
+						PQclear(result);
+						goto error_return;
+					}
 
-		/* print tables inherited from (exclude partitioned parents) */
-		printfPQExpBuffer(&buf,
-						  "SELECT c.oid::pg_catalog.regclass\n"
-						  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
-						  "WHERE c.oid = i.inhparent AND i.inhrelid = '%s'\n"
-						  "  AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_TABLE)
-						  " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_INDEX)
-						  "\nORDER BY inhseqno;",
-						  oid);
+					/* Print server name */
+					printfPQExpBuffer(&buf, _("Server: %s"),
+									  PQgetvalue(result, 0, 0));
+					printTableAddFooter(&cont, buf.data);
 
-		result = PSQLexec(buf.data);
-		if (!result)
-			goto error_return;
-		else
-		{
-			const char *s = _("Inherits");
-			int			sw = pg_wcswidth(s, strlen(s), pset.encoding);
+					/* Print per-table FDW options, if any */
+					ftoptions = PQgetvalue(result, 0, 1);
+					if (ftoptions && ftoptions[0] != '\0')
+					{
+						printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions);
+						printTableAddFooter(&cont, buf.data);
+					}
+					PQclear(result);
+				}
 
-			tuples = PQntuples(result);
+				/* print tables inherited from (exclude partitioned parents) */
+				printfPQExpBuffer(&buf,
+								  "SELECT c.oid::pg_catalog.regclass\n"
+								  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
+								  "WHERE c.oid = i.inhparent AND i.inhrelid = '%s'\n"
+								  "  AND c.relkind != " RelKindAsString(RELKIND_PARTITIONED_TABLE)
+								  " AND c.relkind != " RelKindAsString(RELKIND_PARTITIONED_INDEX)
+								  "\nORDER BY inhseqno;",
+								  oid);
 
-			for (i = 0; i < tuples; i++)
-			{
-				if (i == 0)
-					printfPQExpBuffer(&buf, "%s: %s",
-									  s, PQgetvalue(result, i, 0));
+				result = PSQLexec(buf.data);
+				if (!result)
+					goto error_return;
 				else
-					printfPQExpBuffer(&buf, "%*s  %s",
-									  sw, "", PQgetvalue(result, i, 0));
-				if (i < tuples - 1)
-					appendPQExpBufferChar(&buf, ',');
+				{
+					const char *s = _("Inherits");
+					int			sw = pg_wcswidth(s, strlen(s), pset.encoding);
 
-				printTableAddFooter(&cont, buf.data);
-			}
+					tuples = PQntuples(result);
 
-			PQclear(result);
-		}
+					for (i = 0; i < tuples; i++)
+					{
+						if (i == 0)
+							printfPQExpBuffer(&buf, "%s: %s",
+											  s, PQgetvalue(result, i, 0));
+						else
+							printfPQExpBuffer(&buf, "%*s  %s",
+											  sw, "", PQgetvalue(result, i, 0));
+						if (i < tuples - 1)
+							appendPQExpBufferChar(&buf, ',');
 
-		/* print child tables (with additional info if partitions) */
-		if (pset.sversion >= 100000)
-			printfPQExpBuffer(&buf,
-							  "SELECT c.oid::pg_catalog.regclass, c.relkind,"
-							  " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n"
-							  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
-							  "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
-							  "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
-							  " c.oid::pg_catalog.regclass::pg_catalog.text;",
-							  oid);
-		else if (pset.sversion >= 80300)
-			printfPQExpBuffer(&buf,
-							  "SELECT c.oid::pg_catalog.regclass, c.relkind, NULL\n"
-							  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
-							  "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
-							  "ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;",
-							  oid);
-		else
-			printfPQExpBuffer(&buf,
-							  "SELECT c.oid::pg_catalog.regclass, c.relkind, NULL\n"
-							  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
-							  "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
-							  "ORDER BY c.relname;",
-							  oid);
+						printTableAddFooter(&cont, buf.data);
+					}
 
-		result = PSQLexec(buf.data);
-		if (!result)
-			goto error_return;
-		tuples = PQntuples(result);
+					PQclear(result);
+				}
 
-		/*
-		 * For a partitioned table with no partitions, always print the number
-		 * of partitions as zero, even when verbose output is expected.
-		 * Otherwise, we will not print "Partitions" section for a partitioned
-		 * table without any partitions.
-		 */
-		if (is_partitioned && tuples == 0)
-		{
-			printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples);
-			printTableAddFooter(&cont, buf.data);
-		}
-		else if (!verbose)
-		{
-			/* print the number of child tables, if any */
-			if (tuples > 0)
-			{
-				if (is_partitioned)
-					printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples);
+				/* print child tables (with additional info if partitions) */
+				if (pset.sversion >= 100000)
+					printfPQExpBuffer(&buf,
+									  "SELECT c.oid::pg_catalog.regclass, c.relkind,"
+									  " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n"
+									  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
+									  "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
+									  "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
+									  " c.oid::pg_catalog.regclass::pg_catalog.text;",
+									  oid);
+				else if (pset.sversion >= 80300)
+					printfPQExpBuffer(&buf,
+									  "SELECT c.oid::pg_catalog.regclass, c.relkind, NULL\n"
+									  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
+									  "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
+									  "ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;",
+									  oid);
 				else
-					printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples);
-				printTableAddFooter(&cont, buf.data);
-			}
-		}
-		else
-		{
-			/* display the list of child tables */
-			const char *ct = is_partitioned ? _("Partitions") : _("Child tables");
-			int			ctw = pg_wcswidth(ct, strlen(ct), pset.encoding);
-
-			for (i = 0; i < tuples; i++)
-			{
-				char		child_relkind = *PQgetvalue(result, i, 1);
+					printfPQExpBuffer(&buf,
+									  "SELECT c.oid::pg_catalog.regclass, c.relkind, NULL\n"
+									  "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
+									  "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
+									  "ORDER BY c.relname;",
+									  oid);
+
+				result = PSQLexec(buf.data);
+				if (!result)
+					goto error_return;
+				tuples = PQntuples(result);
 
-				if (i == 0)
-					printfPQExpBuffer(&buf, "%s: %s",
-									  ct, PQgetvalue(result, i, 0));
+				/*
+				 * For a partitioned table with no partitions, always print
+				 * the number of partitions as zero, even when verbose output
+				 * is expected. Otherwise, we will not print "Partitions"
+				 * section for a partitioned table without any partitions.
+				 */
+				if (is_partitioned && tuples == 0)
+				{
+					printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples);
+					printTableAddFooter(&cont, buf.data);
+				}
+				else if (!verbose)
+				{
+					/* print the number of child tables, if any */
+					if (tuples > 0)
+					{
+						if (is_partitioned)
+							printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples);
+						else
+							printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples);
+						printTableAddFooter(&cont, buf.data);
+					}
+				}
 				else
-					printfPQExpBuffer(&buf, "%*s  %s",
-									  ctw, "", PQgetvalue(result, i, 0));
-				if (!PQgetisnull(result, i, 2))
-					appendPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 2));
-				if (child_relkind == RELKIND_PARTITIONED_TABLE ||
-					child_relkind == RELKIND_PARTITIONED_INDEX)
-					appendPQExpBufferStr(&buf, ", PARTITIONED");
-				if (i < tuples - 1)
-					appendPQExpBufferChar(&buf, ',');
+				{
+					/* display the list of child tables */
+					const char *ct = is_partitioned ? _("Partitions") : _("Child tables");
+					int			ctw = pg_wcswidth(ct, strlen(ct), pset.encoding);
 
-				printTableAddFooter(&cont, buf.data);
-			}
-		}
-		PQclear(result);
+					for (i = 0; i < tuples; i++)
+					{
+						char		child_relkind = *PQgetvalue(result, i, 1);
+
+						if (i == 0)
+							printfPQExpBuffer(&buf, "%s: %s",
+											  ct, PQgetvalue(result, i, 0));
+						else
+							printfPQExpBuffer(&buf, "%*s  %s",
+											  ctw, "", PQgetvalue(result, i, 0));
+						if (!PQgetisnull(result, i, 2))
+							appendPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 2));
+						if (child_relkind == RELKIND_PARTITIONED_TABLE ||
+							child_relkind == RELKIND_PARTITIONED_INDEX)
+							appendPQExpBufferStr(&buf, ", PARTITIONED");
+						if (i < tuples - 1)
+							appendPQExpBufferChar(&buf, ',');
 
-		/* Table type */
-		if (tableinfo.reloftype)
-		{
-			printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype);
-			printTableAddFooter(&cont, buf.data);
-		}
+						printTableAddFooter(&cont, buf.data);
+					}
+				}
+				PQclear(result);
 
-		if (verbose &&
-			(tableinfo.relkind == RELKIND_RELATION ||
-			 tableinfo.relkind == RELKIND_MATVIEW) &&
+				/* Table type */
+				if (tableinfo.reloftype)
+				{
+					printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype);
+					printTableAddFooter(&cont, buf.data);
+				}
 
-		/*
-		 * No need to display default values; we already display a REPLICA
-		 * IDENTITY marker on indexes.
-		 */
-			tableinfo.relreplident != 'i' &&
-			((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') ||
-			 (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n')))
-		{
-			const char *s = _("Replica Identity");
+				if (verbose &&
+					(tableinfo.relkind == RELKIND_RELATION ||
+					 tableinfo.relkind == RELKIND_MATVIEW) &&
 
-			printfPQExpBuffer(&buf, "%s: %s",
-							  s,
-							  tableinfo.relreplident == 'f' ? "FULL" :
-							  tableinfo.relreplident == 'n' ? "NOTHING" :
-							  "???");
+				/*
+				 * No need to display default values; we already display a
+				 * REPLICA IDENTITY marker on indexes.
+				 */
+					tableinfo.relreplident != 'i' &&
+					((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') ||
+					 (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n')))
+				{
+					const char *s = _("Replica Identity");
 
-			printTableAddFooter(&cont, buf.data);
-		}
+					printfPQExpBuffer(&buf, "%s: %s",
+									  s,
+									  tableinfo.relreplident == 'f' ? "FULL" :
+									  tableinfo.relreplident == 'n' ? "NOTHING" :
+									  "???");
 
-		/* OIDs, if verbose and not a materialized view */
-		if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
-			printTableAddFooter(&cont, _("Has OIDs: yes"));
+					printTableAddFooter(&cont, buf.data);
+				}
 
-		/* Tablespace info */
-		add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
-							  true);
+				/* OIDs, if verbose and not a materialized view */
+				if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
+					printTableAddFooter(&cont, _("Has OIDs: yes"));
 
-		/* Access method info */
-		if (verbose && tableinfo.relam != NULL && !pset.hide_tableam)
-		{
-			printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
-			printTableAddFooter(&cont, buf.data);
-		}
+				/* Tablespace info */
+				add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
+									  true);
+
+				/* Access method info */
+				if (verbose && tableinfo.relam != NULL && !pset.hide_tableam)
+				{
+					printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
+					printTableAddFooter(&cont, buf.data);
+				}
+			}
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_INDEX:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 
 	/* reloptions, if verbose */
@@ -3348,59 +3478,71 @@ add_tablespace_footer(printTableContent *const cont, char relkind,
 					  Oid tablespace, const bool newline)
 {
 	/* relkinds for which we support tablespaces */
-	if (relkind == RELKIND_RELATION ||
-		relkind == RELKIND_MATVIEW ||
-		relkind == RELKIND_INDEX ||
-		relkind == RELKIND_PARTITIONED_TABLE ||
-		relkind == RELKIND_PARTITIONED_INDEX ||
-		relkind == RELKIND_TOASTVALUE)
+	switch ((RelKind) relkind)
 	{
-		/*
-		 * We ignore the database default tablespace so that users not using
-		 * tablespaces don't need to know about them.  This case also covers
-		 * pre-8.0 servers, for which tablespace will always be 0.
-		 */
-		if (tablespace != 0)
-		{
-			PGresult   *result = NULL;
-			PQExpBufferData buf;
-
-			initPQExpBuffer(&buf);
-			printfPQExpBuffer(&buf,
-							  "SELECT spcname FROM pg_catalog.pg_tablespace\n"
-							  "WHERE oid = '%u';", tablespace);
-			result = PSQLexec(buf.data);
-			if (!result)
-			{
-				termPQExpBuffer(&buf);
-				return;
-			}
-			/* Should always be the case, but.... */
-			if (PQntuples(result) > 0)
+		case RELKIND_RELATION:
+		case RELKIND_MATVIEW:
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_TOASTVALUE:
 			{
-				if (newline)
-				{
-					/* Add the tablespace as a new footer */
-					printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
-									  PQgetvalue(result, 0, 0));
-					printTableAddFooter(cont, buf.data);
-				}
-				else
+				/*
+				 * We ignore the database default tablespace so that users not
+				 * using tablespaces don't need to know about them.  This case
+				 * also covers pre-8.0 servers, for which tablespace will
+				 * always be 0.
+				 */
+				if (tablespace != 0)
 				{
-					/* Append the tablespace to the latest footer */
-					printfPQExpBuffer(&buf, "%s", cont->footer->data);
-
-					/*-------
-					   translator: before this string there's an index description like
-					   '"foo_pkey" PRIMARY KEY, btree (a)' */
-					appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
-									  PQgetvalue(result, 0, 0));
-					printTableSetFooter(cont, buf.data);
+					PGresult   *result = NULL;
+					PQExpBufferData buf;
+
+					initPQExpBuffer(&buf);
+					printfPQExpBuffer(&buf,
+									  "SELECT spcname FROM pg_catalog.pg_tablespace\n"
+									  "WHERE oid = '%u';", tablespace);
+					result = PSQLexec(buf.data);
+					if (!result)
+					{
+						termPQExpBuffer(&buf);
+						return;
+					}
+					/* Should always be the case, but.... */
+					if (PQntuples(result) > 0)
+					{
+						if (newline)
+						{
+							/* Add the tablespace as a new footer */
+							printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
+											  PQgetvalue(result, 0, 0));
+							printTableAddFooter(cont, buf.data);
+						}
+						else
+						{
+							/* Append the tablespace to the latest footer */
+							printfPQExpBuffer(&buf, "%s", cont->footer->data);
+
+							/*-------
+							   translator: before this string there's an index description like
+							   '"foo_pkey" PRIMARY KEY, btree (a)' */
+							appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
+											  PQgetvalue(result, 0, 0));
+							printTableSetFooter(cont, buf.data);
+						}
+					}
+					PQclear(result);
+					termPQExpBuffer(&buf);
 				}
 			}
-			PQclear(result);
-			termPQExpBuffer(&buf);
-		}
+			break;
+		case RELKIND_SEQUENCE:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_VIEW:
+		case RELKIND_NULL:
+		default:
+			break;
 	}
 }
 
@@ -3694,15 +3836,15 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 					  "SELECT n.nspname as \"%s\",\n"
 					  "  c.relname as \"%s\",\n"
 					  "  CASE c.relkind"
-					  " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_RELATION) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_VIEW) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_MATVIEW) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_INDEX) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_SEQUENCE) " THEN '%s'"
 					  " WHEN 's' THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
-					  " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_FOREIGN_TABLE) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
+					  " WHEN " RelKindAsString(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
 					  " END as \"%s\",\n"
 					  "  pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
 					  gettext_noop("Schema"),
@@ -3779,21 +3921,21 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 
 	appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
 	if (showTables)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_RELATION) ","
-							 CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_RELATION) ","
+							 RelKindAsString(RELKIND_PARTITIONED_TABLE) ",");
 	if (showViews)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_VIEW) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_VIEW) ",");
 	if (showMatViews)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_MATVIEW) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_MATVIEW) ",");
 	if (showIndexes)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_INDEX) ","
-							 CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_INDEX) ","
+							 RelKindAsString(RELKIND_PARTITIONED_INDEX) ",");
 	if (showSeq)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_SEQUENCE) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_SEQUENCE) ",");
 	if (showSystem || pattern)
 		appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
 	if (showForeign)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_FOREIGN_TABLE) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_FOREIGN_TABLE) ",");
 
 	appendPQExpBufferStr(&buf, "''");	/* dummy */
 	appendPQExpBufferStr(&buf, ")\n");
@@ -3921,8 +4063,8 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n  CASE c.relkind"
-						  " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
-						  " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
+						  " WHEN " RelKindAsString(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
+						  " WHEN " RelKindAsString(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
 						  " END as \"%s\"",
 						  gettext_noop("partitioned table"),
 						  gettext_noop("partitioned index"),
@@ -4012,9 +4154,9 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
 	if (showTables)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_PARTITIONED_TABLE) ",");
 	if (showIndexes)
-		appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
+		appendPQExpBufferStr(&buf, RelKindAsString(RELKIND_PARTITIONED_INDEX) ",");
 	appendPQExpBufferStr(&buf, "''");	/* dummy */
 	appendPQExpBufferStr(&buf, ")\n");
 
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index eb018854a5..c56beb579b 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -354,7 +354,7 @@ static const SchemaQuery Query_for_list_of_datatypes = {
 	.catname = "pg_catalog.pg_type t",
 	/* selcondition --- ignore table rowtypes and array types */
 	.selcondition = "(t.typrelid = 0 "
-	" OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
+	" OR (SELECT c.relkind = " RelKindAsString(RELKIND_COMPOSITE_TYPE)
 	"     FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
 	"AND t.typname !~ '^_'",
 	.viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
@@ -366,7 +366,7 @@ static const SchemaQuery Query_for_list_of_datatypes = {
 static const SchemaQuery Query_for_list_of_composite_datatypes = {
 	.catname = "pg_catalog.pg_type t",
 	/* selcondition --- only get composite types */
-	.selcondition = "(SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
+	.selcondition = "(SELECT c.relkind = " RelKindAsString(RELKIND_COMPOSITE_TYPE)
 	" FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) "
 	"AND t.typname !~ '^_'",
 	.viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
@@ -425,7 +425,7 @@ static const SchemaQuery Query_for_list_of_routines = {
 
 static const SchemaQuery Query_for_list_of_sequences = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
+	.selcondition = "c.relkind IN (" RelKindAsString(RELKIND_SEQUENCE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -433,7 +433,7 @@ static const SchemaQuery Query_for_list_of_sequences = {
 
 static const SchemaQuery Query_for_list_of_foreign_tables = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
+	.selcondition = "c.relkind IN (" RelKindAsString(RELKIND_FOREIGN_TABLE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -442,8 +442,8 @@ static const SchemaQuery Query_for_list_of_foreign_tables = {
 static const SchemaQuery Query_for_list_of_tables = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-	CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+	RelKindAsString(RELKIND_PARTITIONED_TABLE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -451,7 +451,7 @@ static const SchemaQuery Query_for_list_of_tables = {
 
 static const SchemaQuery Query_for_list_of_partitioned_tables = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
+	.selcondition = "c.relkind IN (" RelKindAsString(RELKIND_PARTITIONED_TABLE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -459,7 +459,7 @@ static const SchemaQuery Query_for_list_of_partitioned_tables = {
 
 static const SchemaQuery Query_for_list_of_views = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
+	.selcondition = "c.relkind IN (" RelKindAsString(RELKIND_VIEW) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -467,7 +467,7 @@ static const SchemaQuery Query_for_list_of_views = {
 
 static const SchemaQuery Query_for_list_of_matviews = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
+	.selcondition = "c.relkind IN (" RelKindAsString(RELKIND_MATVIEW) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -476,8 +476,8 @@ static const SchemaQuery Query_for_list_of_matviews = {
 static const SchemaQuery Query_for_list_of_indexes = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_INDEX) ", "
-	CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_INDEX) ", "
+	RelKindAsString(RELKIND_PARTITIONED_INDEX) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -485,7 +485,7 @@ static const SchemaQuery Query_for_list_of_indexes = {
 
 static const SchemaQuery Query_for_list_of_partitioned_indexes = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind = " CppAsString2(RELKIND_PARTITIONED_INDEX),
+	.selcondition = "c.relkind = " RelKindAsString(RELKIND_PARTITIONED_INDEX),
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -503,8 +503,8 @@ static const SchemaQuery Query_for_list_of_relations = {
 /* partitioned relations */
 static const SchemaQuery Query_for_list_of_partitioned_relations = {
 	.catname = "pg_catalog.pg_class c",
-	.selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE)
-	", " CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
+	.selcondition = "c.relkind IN (" RelKindAsString(RELKIND_PARTITIONED_TABLE)
+	", " RelKindAsString(RELKIND_PARTITIONED_INDEX) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -521,10 +521,10 @@ static const SchemaQuery Query_for_list_of_operator_families = {
 static const SchemaQuery Query_for_list_of_updatables = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-	CppAsString2(RELKIND_FOREIGN_TABLE) ", "
-	CppAsString2(RELKIND_VIEW) ", "
-	CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+	RelKindAsString(RELKIND_FOREIGN_TABLE) ", "
+	RelKindAsString(RELKIND_VIEW) ", "
+	RelKindAsString(RELKIND_PARTITIONED_TABLE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -534,12 +534,12 @@ static const SchemaQuery Query_for_list_of_updatables = {
 static const SchemaQuery Query_for_list_of_selectables = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-	CppAsString2(RELKIND_SEQUENCE) ", "
-	CppAsString2(RELKIND_VIEW) ", "
-	CppAsString2(RELKIND_MATVIEW) ", "
-	CppAsString2(RELKIND_FOREIGN_TABLE) ", "
-	CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+	RelKindAsString(RELKIND_SEQUENCE) ", "
+	RelKindAsString(RELKIND_VIEW) ", "
+	RelKindAsString(RELKIND_MATVIEW) ", "
+	RelKindAsString(RELKIND_FOREIGN_TABLE) ", "
+	RelKindAsString(RELKIND_PARTITIONED_TABLE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -552,10 +552,10 @@ static const SchemaQuery Query_for_list_of_selectables = {
 static const SchemaQuery Query_for_list_of_analyzables = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-	CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
-	CppAsString2(RELKIND_MATVIEW) ", "
-	CppAsString2(RELKIND_FOREIGN_TABLE) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+	RelKindAsString(RELKIND_PARTITIONED_TABLE) ", "
+	RelKindAsString(RELKIND_MATVIEW) ", "
+	RelKindAsString(RELKIND_FOREIGN_TABLE) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -565,9 +565,9 @@ static const SchemaQuery Query_for_list_of_analyzables = {
 static const SchemaQuery Query_for_list_of_indexables = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-	CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
-	CppAsString2(RELKIND_MATVIEW) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+	RelKindAsString(RELKIND_PARTITIONED_TABLE) ", "
+	RelKindAsString(RELKIND_MATVIEW) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
@@ -577,8 +577,8 @@ static const SchemaQuery Query_for_list_of_indexables = {
 static const SchemaQuery Query_for_list_of_vacuumables = {
 	.catname = "pg_catalog.pg_class c",
 	.selcondition =
-	"c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-	CppAsString2(RELKIND_MATVIEW) ")",
+	"c.relkind IN (" RelKindAsString(RELKIND_RELATION) ", "
+	RelKindAsString(RELKIND_MATVIEW) ")",
 	.viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
 	.namespace = "c.relnamespace",
 	.result = "pg_catalog.quote_ident(c.relname)",
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index b7b19ccc1c..1b921a1483 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -621,8 +621,8 @@ get_parallel_object_list(PGconn *conn, ReindexType type,
 							  " ON c.relnamespace = ns.oid\n"
 							  " WHERE ns.nspname != 'pg_catalog'\n"
 							  "   AND c.relkind IN ("
-							  CppAsString2(RELKIND_RELATION) ", "
-							  CppAsString2(RELKIND_MATVIEW) ")\n"
+							  RelKindAsString(RELKIND_RELATION) ", "
+							  RelKindAsString(RELKIND_MATVIEW) ")\n"
 							  " ORDER BY c.relpages DESC;");
 			break;
 
@@ -643,8 +643,8 @@ get_parallel_object_list(PGconn *conn, ReindexType type,
 								  " JOIN pg_catalog.pg_namespace ns"
 								  " ON c.relnamespace = ns.oid\n"
 								  " WHERE c.relkind IN ("
-								  CppAsString2(RELKIND_RELATION) ", "
-								  CppAsString2(RELKIND_MATVIEW) ")\n"
+								  RelKindAsString(RELKIND_RELATION) ", "
+								  RelKindAsString(RELKIND_MATVIEW) ")\n"
 								  " AND ns.nspname IN (");
 
 				for (cell = user_list->head; cell; cell = cell->next)
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
index 6a3c941158..9a90e820f4 100644
--- a/src/bin/scripts/vacuumdb.c
+++ b/src/bin/scripts/vacuumdb.c
@@ -573,8 +573,8 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
 	if (!tables_listed)
 	{
 		appendPQExpBufferStr(&catalog_query, " WHERE c.relkind OPERATOR(pg_catalog.=) ANY (array["
-							 CppAsString2(RELKIND_RELATION) ", "
-							 CppAsString2(RELKIND_MATVIEW) "])\n");
+							 RelKindAsString(RELKIND_RELATION) ", "
+							 RelKindAsString(RELKIND_MATVIEW) "])\n");
 		has_where = true;
 	}
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 78b33b2a7f..6e9955fe6a 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -154,16 +154,34 @@ typedef FormData_pg_class *Form_pg_class;
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
-#define		  RELKIND_RELATION		  'r'	/* ordinary table */
-#define		  RELKIND_INDEX			  'i'	/* secondary index */
-#define		  RELKIND_SEQUENCE		  'S'	/* sequence object */
-#define		  RELKIND_TOASTVALUE	  't'	/* for out-of-line values */
-#define		  RELKIND_VIEW			  'v'	/* view */
-#define		  RELKIND_MATVIEW		  'm'	/* materialized view */
-#define		  RELKIND_COMPOSITE_TYPE  'c'	/* composite type */
-#define		  RELKIND_FOREIGN_TABLE   'f'	/* foreign table */
-#define		  RELKIND_PARTITIONED_TABLE 'p' /* partitioned table */
-#define		  RELKIND_PARTITIONED_INDEX 'I' /* partitioned index */
+typedef enum RelKind
+{
+	RELKIND_RELATION = 'r',		/* ordinary table */
+	RELKIND_INDEX = 'i',		/* secondary index */
+	RELKIND_SEQUENCE = 'S',		/* sequence object */
+	RELKIND_TOASTVALUE = 't',	/* for out-of-line values */
+	RELKIND_VIEW = 'v',			/* view */
+	RELKIND_MATVIEW = 'm',		/* materialized view */
+	RELKIND_COMPOSITE_TYPE = 'c',	/* composite type */
+	RELKIND_FOREIGN_TABLE = 'f',	/* foreign table */
+	RELKIND_PARTITIONED_TABLE = 'p',	/* partitioned table */
+	RELKIND_PARTITIONED_INDEX = 'I',	/* partitioned index */
+	RELKIND_NULL = '\0'			/* unset */
+} RelKind;
+
+#define chr_RELKIND_RELATION			'r'
+#define chr_RELKIND_INDEX				'i'
+#define chr_RELKIND_SEQUENCE			'S'
+#define chr_RELKIND_TOASTVALUE			't'
+#define chr_RELKIND_VIEW				'v'
+#define chr_RELKIND_MATVIEW				'm'
+#define chr_RELKIND_COMPOSITE_TYPE		'c'
+#define chr_RELKIND_FOREIGN_TABLE		'f'
+#define chr_RELKIND_PARTITIONED_TABLE	'p'
+#define chr_RELKIND_PARTITIONED_INDEX	'I'
+#define chr_RELKIND_NULL				'\0'
+
+#define RelKindAsString(x) CppAsString2(chr_##x)
 
 #define		  RELPERSISTENCE_PERMANENT	'p' /* regular table */
 #define		  RELPERSISTENCE_UNLOGGED	'u' /* unlogged permanent table */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f5dfa32d55..a9a2bf1fb6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2110,7 +2110,7 @@ typedef struct AggregateInstrumentation
 	Size		hash_mem_peak;	/* peak hash table memory usage */
 	uint64		hash_disk_used; /* kB of disk space used */
 	int			hash_batches_used;	/* batches used during entire execution */
-} AggregateInstrumentation;
+}			AggregateInstrumentation;
 
 /* ----------------
  *	 Shared memory container for per-worker aggregate information
@@ -2120,7 +2120,7 @@ typedef struct SharedAggInfo
 {
 	int			num_workers;
 	AggregateInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
-} SharedAggInfo;
+}			SharedAggInfo;
 
 /* ---------------------
  *	AggState information
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index b20e2ad4f6..65602a8763 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -81,7 +81,7 @@ typedef enum
 	PROC_WAIT_STATUS_OK,
 	PROC_WAIT_STATUS_WAITING,
 	PROC_WAIT_STATUS_ERROR,
-} ProcWaitStatus;
+}			ProcWaitStatus;
 
 /*
  * Each backend has a PGPROC struct in shared memory.  There is also a list of
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index f8595642da..e92617111d 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -47,11 +47,11 @@ extern int	namestrcmp(Name name, const char *str);
 extern int32 pg_atoi(const char *s, int size, int c);
 extern int16 pg_strtoint16(const char *s);
 extern int32 pg_strtoint32(const char *s);
-extern int pg_itoa(int16 i, char *a);
-extern int pg_ultoa_n(uint32 l, char *a);
-extern int pg_ulltoa_n(uint64 l, char *a);
-extern int pg_ltoa(int32 l, char *a);
-extern int pg_lltoa(int64 ll, char *a);
+extern int	pg_itoa(int16 i, char *a);
+extern int	pg_ultoa_n(uint32 l, char *a);
+extern int	pg_ulltoa_n(uint64 l, char *a);
+extern int	pg_ltoa(int32 l, char *a);
+extern int	pg_lltoa(int64 ll, char *a);
 extern char *pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth);
 extern char *pg_ultostr(char *str, uint32 value);
 extern uint64 pg_strtouint64(const char *str, char **endptr, int base);
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 828ff5a288..6a13603bb5 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1723,14 +1723,23 @@ plpgsql_parse_cwordtype(List *idents)
 	 * It must be a relation, sequence, view, materialized view, composite
 	 * type, or foreign table
 	 */
-	if (classStruct->relkind != RELKIND_RELATION &&
-		classStruct->relkind != RELKIND_SEQUENCE &&
-		classStruct->relkind != RELKIND_VIEW &&
-		classStruct->relkind != RELKIND_MATVIEW &&
-		classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
-		classStruct->relkind != RELKIND_FOREIGN_TABLE &&
-		classStruct->relkind != RELKIND_PARTITIONED_TABLE)
-		goto done;
+	switch ((RelKind) classStruct->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_SEQUENCE:
+		case RELKIND_VIEW:
+		case RELKIND_MATVIEW:
+		case RELKIND_COMPOSITE_TYPE:
+		case RELKIND_FOREIGN_TABLE:
+		case RELKIND_PARTITIONED_TABLE:
+			break;
+		case RELKIND_PARTITIONED_INDEX:
+		case RELKIND_INDEX:
+		case RELKIND_TOASTVALUE:
+		case RELKIND_NULL:
+		default:
+			goto done;
+	}
 
 	/*
 	 * Fetch the named table field and its type
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 02397f2eb1..87453751b0 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -816,7 +816,7 @@ test_spinlock(void)
 			char		data_before[4];
 			slock_t		lock;
 			char		data_after[4];
-		} struct_w_lock;
+		}			struct_w_lock;
 
 		memcpy(struct_w_lock.data_before, "abcd", 4);
 		memcpy(struct_w_lock.data_after, "ef12", 4);
@@ -864,28 +864,28 @@ test_spinlock(void)
 	}
 
 	/*
-	 * Ensure that allocating more than INT32_MAX emulated spinlocks
-	 * works. That's interesting because the spinlock emulation uses a 32bit
-	 * integer to map spinlocks onto semaphores. There've been bugs...
+	 * Ensure that allocating more than INT32_MAX emulated spinlocks works.
+	 * That's interesting because the spinlock emulation uses a 32bit integer
+	 * to map spinlocks onto semaphores. There've been bugs...
 	 */
 #ifndef HAVE_SPINLOCKS
 	{
 		/*
-		 * Initialize enough spinlocks to advance counter close to
-		 * wraparound. It's too expensive to perform acquire/release for each,
-		 * as those may be syscalls when the spinlock emulation is used (and
-		 * even just atomic TAS would be expensive).
+		 * Initialize enough spinlocks to advance counter close to wraparound.
+		 * It's too expensive to perform acquire/release for each, as those
+		 * may be syscalls when the spinlock emulation is used (and even just
+		 * atomic TAS would be expensive).
 		 */
 		for (uint32 i = 0; i < INT32_MAX - 100000; i++)
 		{
-			slock_t lock;
+			slock_t		lock;
 
 			SpinLockInit(&lock);
 		}
 
 		for (uint32 i = 0; i < 200000; i++)
 		{
-			slock_t lock;
+			slock_t		lock;
 
 			SpinLockInit(&lock);
 
@@ -915,7 +915,7 @@ test_spinlock(void)
 static void
 test_atomic_spin_nest(void)
 {
-	slock_t lock;
+	slock_t		lock;
 #define NUM_TEST_ATOMICS (NUM_SPINLOCK_SEMAPHORES + NUM_ATOMICS_SEMAPHORES + 27)
 	pg_atomic_uint32 atomics32[NUM_TEST_ATOMICS];
 	pg_atomic_uint64 atomics64[NUM_TEST_ATOMICS];
diff --git a/src/tools/findoidjoins/findoidjoins.c b/src/tools/findoidjoins/findoidjoins.c
index 5239332ea7..3961804b10 100644
--- a/src/tools/findoidjoins/findoidjoins.c
+++ b/src/tools/findoidjoins/findoidjoins.c
@@ -62,7 +62,7 @@ main(int argc, char **argv)
 					  "SELECT c.relname, (SELECT nspname FROM "
 					  "pg_catalog.pg_namespace n WHERE n.oid = c.relnamespace) AS nspname "
 					  "FROM pg_catalog.pg_class c "
-					  "WHERE c.relkind = " CppAsString2(RELKIND_RELATION)
+					  "WHERE c.relkind = " RelKindAsString(RELKIND_RELATION)
 					  " AND c.oid < '%u'"
 					  " AND EXISTS(SELECT * FROM pg_attribute a"
 					  "            WHERE a.attrelid = c.oid AND a.attname = 'oid' "
@@ -88,7 +88,7 @@ main(int argc, char **argv)
 					  "FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a "
 					  "WHERE a.attnum > 0"
 					  " AND a.attname != 'oid'"
-					  " AND c.relkind = " CppAsString2(RELKIND_RELATION)
+					  " AND c.relkind = " RelKindAsString(RELKIND_RELATION)
 					  " AND c.oid < '%u'"
 					  " AND a.attrelid = c.oid"
 					  " AND a.atttypid IN ('pg_catalog.oid'::regtype, "
@@ -166,7 +166,7 @@ main(int argc, char **argv)
 					  "a.attname "
 					  "FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a "
 					  "WHERE a.attnum > 0"
-					  " AND c.relkind = " CppAsString2(RELKIND_RELATION)
+					  " AND c.relkind = " RelKindAsString(RELKIND_RELATION)
 					  " AND a.attrelid = c.oid"
 					  " AND a.atttypid IN ('pg_catalog.oid[]'::regtype, "
 					  " 'pg_catalog.oidvector'::regtype, "
-- 
2.21.1 (Apple Git-122.3)