From 64ab49d9ff8b59ff93a4b76c4f70fb162b386724 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <alvherre@kurilemu.de>
Date: Fri, 31 Oct 2025 14:07:45 +0100
Subject: [PATCH 3/3] Initial steps to making relkind an enum

---
 contrib/pg_overexplain/pg_overexplain.c      |  4 +---
 contrib/pg_prewarm/pg_prewarm.c              |  2 +-
 contrib/postgres_fdw/postgres_fdw.c          |  2 +-
 contrib/sepgsql/dml.c                        |  2 +-
 contrib/sepgsql/relation.c                   | 14 +++++------
 src/backend/access/common/reloptions.c       |  2 +-
 src/backend/catalog/aclchk.c                 |  6 ++---
 src/backend/catalog/heap.c                   | 14 +++++------
 src/backend/catalog/index.c                  |  2 +-
 src/backend/catalog/objectaddress.c          |  2 +-
 src/backend/catalog/pg_class.c               |  2 +-
 src/backend/catalog/pg_publication.c         |  6 ++---
 src/backend/catalog/pg_subscription.c        |  4 ++--
 src/backend/commands/copyto.c                |  2 +-
 src/backend/commands/createas.c              |  2 +-
 src/backend/commands/indexcmds.c             | 12 +++++-----
 src/backend/commands/lockcmds.c              |  4 ++--
 src/backend/commands/policy.c                |  2 +-
 src/backend/commands/publicationcmds.c       |  2 +-
 src/backend/commands/subscriptioncmds.c      |  8 +++----
 src/backend/commands/tablecmds.c             | 16 ++++++-------
 src/backend/commands/trigger.c               |  2 +-
 src/backend/executor/nodeModifyTable.c       |  4 ++--
 src/backend/nodes/gen_node_support.pl        |  3 ++-
 src/backend/optimizer/util/appendinfo.c      |  2 +-
 src/backend/replication/pgoutput/pgoutput.c  |  2 +-
 src/backend/statistics/stat_utils.c          |  2 +-
 src/backend/tcop/utility.c                   |  2 +-
 src/backend/utils/activity/pgstat_relation.c |  2 +-
 src/backend/utils/adt/acl.c                  |  6 ++---
 src/backend/utils/adt/partitionfuncs.c       |  4 ++--
 src/backend/utils/adt/ruleutils.c            |  2 +-
 src/backend/utils/cache/lsyscache.c          |  6 ++---
 src/backend/utils/cache/relcache.c           |  2 +-
 src/bin/pg_dump/pg_backup_archiver.c         |  2 +-
 src/bin/pg_dump/pg_backup_archiver.h         |  5 ++--
 src/bin/pg_dump/pg_dump.c                    | 10 ++++----
 src/bin/pg_dump/pg_dump.h                    |  6 ++---
 src/bin/pgbench/pgbench.c                    |  2 +-
 src/bin/psql/describe.c                      |  6 ++---
 src/include/access/reloptions.h              |  3 ++-
 src/include/catalog/heap.h                   |  7 +++---
 src/include/catalog/objectaddress.h          |  2 +-
 src/include/catalog/pg_class.h               | 25 +++++++++++---------
 src/include/catalog/pg_publication.h         |  2 +-
 src/include/commands/tablecmds.h             |  2 +-
 src/include/nodes/parsenodes.h               |  3 ++-
 src/include/replication/logicalproto.h       |  2 +-
 src/include/utils/lsyscache.h                |  3 ++-
 src/include/utils/relcache.h                 |  3 ++-
 50 files changed, 120 insertions(+), 112 deletions(-)

diff --git a/contrib/pg_overexplain/pg_overexplain.c b/contrib/pg_overexplain/pg_overexplain.c
index 316ffd1c87f..d575d462d97 100644
--- a/contrib/pg_overexplain/pg_overexplain.c
+++ b/contrib/pg_overexplain/pg_overexplain.c
@@ -534,10 +534,8 @@ overexplain_range_table(PlannedStmt *plannedstmt, ExplainState *es)
 			case RELKIND_PARTITIONED_INDEX:
 				relkind = "partitioned_index";
 				break;
-			case '\0':
-				relkind = NULL;
-				break;
 			default:
+				pg_unreachable();
 				relkind = psprintf("%c", rte->relkind);
 				break;
 		}
diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index c2716086693..f320a0e3831 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -73,7 +73,7 @@ pg_prewarm(PG_FUNCTION_ARGS)
 	char	   *ttype;
 	PrewarmType ptype;
 	AclResult	aclresult;
-	char		relkind;
+	Relkind		relkind;
 	Oid			privOid;
 
 	/* Basic sanity checking. */
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index e0457bb1253..5ff70f7ddfa 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -4951,7 +4951,7 @@ postgresGetAnalyzeInfoForForeignTable(Relation relation, bool *can_tablesample)
 	StringInfoData sql;
 	PGresult   *res;
 	double		reltuples;
-	char		relkind;
+	Relkind		relkind;
 
 	/* assume the remote relation does not support TABLESAMPLE */
 	*can_tablesample = false;
diff --git a/contrib/sepgsql/dml.c b/contrib/sepgsql/dml.c
index b44d09e447f..4f5864b22da 100644
--- a/contrib/sepgsql/dml.c
+++ b/contrib/sepgsql/dml.c
@@ -150,7 +150,7 @@ check_relation_privileges(Oid relOid,
 	char	   *audit_name;
 	Bitmapset  *columns;
 	int			index;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 	bool		result = true;
 
 	/*
diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c
index 5c61e1f4c81..a77a8b5a846 100644
--- a/contrib/sepgsql/relation.c
+++ b/contrib/sepgsql/relation.c
@@ -52,7 +52,7 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
 	ObjectAddress object;
 	Form_pg_attribute attForm;
 	StringInfoData audit_name;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 
 	/*
 	 * Only attributes within regular relations or partition relations have
@@ -134,7 +134,7 @@ sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
 {
 	ObjectAddress object;
 	char	   *audit_name;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 
 	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
 		return;
@@ -167,7 +167,7 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
 {
 	ObjectAddress object;
 	char	   *audit_name;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 
 	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
 		ereport(ERROR,
@@ -210,7 +210,7 @@ sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
 {
 	ObjectAddress object;
 	char	   *audit_name;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 
 	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
 		return;
@@ -418,7 +418,7 @@ sepgsql_relation_drop(Oid relOid)
 	ObjectAddress object;
 	char	   *audit_name;
 	uint16_t	tclass = 0;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 
 	switch (relkind)
 	{
@@ -526,7 +526,7 @@ sepgsql_relation_truncate(Oid relOid)
 	ObjectAddress object;
 	char	   *audit_name;
 	uint16_t	tclass = 0;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 
 	switch (relkind)
 	{
@@ -565,7 +565,7 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
 {
 	ObjectAddress object;
 	char	   *audit_name;
-	char		relkind = get_rel_relkind(relOid);
+	Relkind		relkind = get_rel_relkind(relOid);
 	uint16_t	tclass = 0;
 
 	if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 237ab8d0ed9..00b3588cded 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -2149,7 +2149,7 @@ view_reloptions(Datum reloptions, bool validate)
  * Parse options for heaps, views and toast tables.
  */
 bytea *
-heap_reloptions(char relkind, Datum reloptions, bool validate)
+heap_reloptions(Relkind relkind, Datum reloptions, bool validate)
 {
 	StdRdOptions *rdopts;
 
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index a431fc0926f..18a43e15509 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -123,7 +123,7 @@ static void SetDefaultACL(InternalDefaultACL *iacls);
 static List *objectNamesToOids(ObjectType objtype, List *objnames,
 							   bool is_grant);
 static List *objectsInSchemaToOids(ObjectType objtype, List *nspnames);
-static List *getRelationsInNamespace(Oid namespaceId, char relkind);
+static List *getRelationsInNamespace(Oid namespaceId, Relkind relkind);
 static void expand_col_privileges(List *colnames, Oid table_oid,
 								  AclMode this_privileges,
 								  AclMode *col_privileges,
@@ -875,7 +875,7 @@ objectsInSchemaToOids(ObjectType objtype, List *nspnames)
  * Return Oid list of relations in given namespace filtered by relation kind
  */
 static List *
-getRelationsInNamespace(Oid namespaceId, char relkind)
+getRelationsInNamespace(Oid namespaceId, Relkind relkind)
 {
 	List	   *relations = NIL;
 	ScanKeyData key[2];
@@ -890,7 +890,7 @@ getRelationsInNamespace(Oid namespaceId, char relkind)
 	ScanKeyInit(&key[1],
 				Anum_pg_class_relkind,
 				BTEqualStrategyNumber, F_CHAREQ,
-				CharGetDatum(relkind));
+				CharGetDatum((char) relkind));
 
 	rel = table_open(RelationRelationId, AccessShareLock);
 	scan = table_beginscan_catalog(rel, 2, key);
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 606434823cf..fa17893855d 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -89,7 +89,7 @@ static void AddNewRelationTuple(Relation pg_class_desc,
 								Oid new_type_oid,
 								Oid reloftype,
 								Oid relowner,
-								char relkind,
+								Relkind relkind,
 								TransactionId relfrozenxid,
 								TransactionId relminmxid,
 								Datum relacl,
@@ -289,7 +289,7 @@ heap_create(const char *relname,
 			RelFileNumber relfilenumber,
 			Oid accessmtd,
 			TupleDesc tupDesc,
-			char relkind,
+			Relkind relkind,
 			char relpersistence,
 			bool shared_relation,
 			bool mapped_relation,
@@ -449,7 +449,7 @@ heap_create(const char *relname,
  * --------------------------------
  */
 void
-CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
+CheckAttributeNamesTypes(TupleDesc tupdesc, Relkind relkind,
 						 int flags)
 {
 	int			i;
@@ -833,7 +833,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
 static void
 AddNewAttributeTuples(Oid new_rel_oid,
 					  TupleDesc tupdesc,
-					  char relkind)
+					  Relkind relkind)
 {
 	Relation	rel;
 	CatalogIndexState indstate;
@@ -939,7 +939,7 @@ InsertPgClassTuple(Relation pg_class_desc,
 	values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
 	values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
 	values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
-	values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
+	values[Anum_pg_class_relkind - 1] = CharGetDatum((char) rd_rel->relkind);
 	values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
 	values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
 	values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
@@ -987,7 +987,7 @@ AddNewRelationTuple(Relation pg_class_desc,
 					Oid new_type_oid,
 					Oid reloftype,
 					Oid relowner,
-					char relkind,
+					Relkind relkind,
 					TransactionId relfrozenxid,
 					TransactionId relminmxid,
 					Datum relacl,
@@ -1129,7 +1129,7 @@ heap_create_with_catalog(const char *relname,
 						 Oid accessmtd,
 						 TupleDesc tupdesc,
 						 List *cooked_constraints,
-						 char relkind,
+						 Relkind relkind,
 						 char relpersistence,
 						 bool shared_relation,
 						 bool mapped_relation,
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 43de42ce39e..ede4546ecee 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -757,7 +757,7 @@ index_create(Relation heapRelation,
 	bool		invalid = (flags & INDEX_CREATE_INVALID) != 0;
 	bool		concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
 	bool		partitioned = (flags & INDEX_CREATE_PARTITIONED) != 0;
-	char		relkind;
+	Relkind		relkind;
 	TransactionId relfrozenxid;
 	MultiXactId relminmxid;
 	bool		create_storage = !RelFileNumberIsValid(relFileNumber);
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 02af64b82c6..93b6e26d067 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -6182,7 +6182,7 @@ strlist_to_textarray(List *list)
  * message saying "table" than fail entirely.
  */
 ObjectType
-get_relkind_objtype(char relkind)
+get_relkind_objtype(Relkind relkind)
 {
 	switch (relkind)
 	{
diff --git a/src/backend/catalog/pg_class.c b/src/backend/catalog/pg_class.c
index 38cf89f09fa..a841ed20868 100644
--- a/src/backend/catalog/pg_class.c
+++ b/src/backend/catalog/pg_class.c
@@ -21,7 +21,7 @@
  * operation.
  */
 int
-errdetail_relkind_not_supported(char relkind)
+errdetail_relkind_not_supported(Relkind relkind)
 {
 	switch (relkind)
 	{
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 9a4791c573e..624ebd59697 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -866,7 +866,7 @@ GetAllTablesPublications(void)
  * publication.
  */
 List *
-GetAllPublicationRelations(char relkind, bool pubviaroot)
+GetAllPublicationRelations(Relkind relkind, bool pubviaroot)
 {
 	Relation	classRel;
 	ScanKeyData key[1];
@@ -881,7 +881,7 @@ GetAllPublicationRelations(char relkind, bool pubviaroot)
 	ScanKeyInit(&key[0],
 				Anum_pg_class_relkind,
 				BTEqualStrategyNumber, F_CHAREQ,
-				CharGetDatum(relkind));
+				CharGetDatum((char) relkind));
 
 	scan = table_beginscan_catalog(classRel, 1, key);
 
@@ -1016,7 +1016,7 @@ GetSchemaPublicationRelations(Oid schemaid, PublicationPartOpt pub_partopt)
 	{
 		Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple);
 		Oid			relid = relForm->oid;
-		char		relkind;
+		Relkind		relkind;
 
 		if (!is_publishable_class(relid, relForm))
 			continue;
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index 2b103245290..988e80c2c31 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -537,7 +537,7 @@ HasSubscriptionTables(Oid subid)
 	while (HeapTupleIsValid(tup = systable_getnext(scan)))
 	{
 		Form_pg_subscription_rel subrel;
-		char		relkind;
+		Relkind		relkind;
 
 		subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
 		relkind = get_rel_relkind(subrel->srrelid);
@@ -600,7 +600,7 @@ GetSubscriptionRelations(Oid subid, bool tables, bool sequences,
 		SubscriptionRelState *relstate;
 		Datum		d;
 		bool		isnull;
-		char		relkind;
+		Relkind		relkind;
 
 		subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
 
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index 4ab4a3893d5..8d7530ea03b 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -692,7 +692,7 @@ BeginCopyTo(ParseState *pstate,
 
 			foreach_oid(child, children)
 			{
-				char		relkind = get_rel_relkind(child);
+				Relkind		relkind = get_rel_relkind(child);
 
 				if (relkind == RELKIND_FOREIGN_TABLE)
 				{
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 270e9bf3110..b05161a9aab 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -83,7 +83,7 @@ create_ctas_internal(List *attrList, IntoClause *into)
 {
 	CreateStmt *create = makeNode(CreateStmt);
 	bool		is_matview;
-	char		relkind;
+	Relkind		relkind;
 	Datum		toast_options;
 	const char *const validnsps[] = HEAP_RELOPT_NAMESPACES;
 	ObjectAddress intoRelationAddr;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 635679cc1f2..dfb15f91931 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -133,7 +133,7 @@ typedef struct ReindexErrorInfo
 {
 	char	   *relname;
 	char	   *relnamespace;
-	char		relkind;
+	Relkind		relkind;
 } ReindexErrorInfo;
 
 /*
@@ -2947,7 +2947,7 @@ ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLev
 	struct ReindexIndexCallbackState state;
 	Oid			indOid;
 	char		persistence;
-	char		relkind;
+	Relkind		relkind;
 
 	/*
 	 * Find and lock index, and check permissions on table; use callback to
@@ -2998,7 +2998,7 @@ static void
 RangeVarCallbackForReindexIndex(const RangeVar *relation,
 								Oid relId, Oid oldRelId, void *arg)
 {
-	char		relkind;
+	Relkind		relkind;
 	struct ReindexIndexCallbackState *state = arg;
 	LOCKMODE	table_lockmode;
 	Oid			table_oid;
@@ -3373,7 +3373,7 @@ static void
 ReindexPartitions(const ReindexStmt *stmt, Oid relid, const ReindexParams *params, bool isTopLevel)
 {
 	List	   *partitions = NIL;
-	char		relkind = get_rel_relkind(relid);
+	Relkind		relkind = get_rel_relkind(relid);
 	char	   *relname = get_rel_name(relid);
 	char	   *relnamespace = get_namespace_name(get_rel_namespace(relid));
 	MemoryContext reindex_context;
@@ -3474,7 +3474,7 @@ ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids, const Reind
 	foreach(l, relids)
 	{
 		Oid			relid = lfirst_oid(l);
-		char		relkind;
+		Relkind		relkind;
 		char		relpersistence;
 
 		StartTransactionCommand();
@@ -3608,7 +3608,7 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
 			   *lc2;
 	MemoryContext private_context;
 	MemoryContext oldcontext;
-	char		relkind;
+	Relkind		relkind;
 	char	   *relationName = NULL;
 	char	   *relationNamespace = NULL;
 	PGRUsage	ru0;
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index f66b8f17b9b..416fb4fe7fe 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -72,7 +72,7 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
 							 void *arg)
 {
 	LOCKMODE	lockmode = *(LOCKMODE *) arg;
-	char		relkind;
+	Relkind		relkind;
 	char		relpersistence;
 	AclResult	aclresult;
 
@@ -190,7 +190,7 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 			AclResult	aclresult;
 
 			Oid			relid = rte->relid;
-			char		relkind = rte->relkind;
+			Relkind		relkind = rte->relkind;
 			char	   *relname = get_rel_name(relid);
 
 			/* Currently, we only allow plain tables or views to be locked. */
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 21b8eebe32d..3aee2444a80 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -66,7 +66,7 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
 {
 	HeapTuple	tuple;
 	Form_pg_class classform;
-	char		relkind;
+	Relkind		relkind;
 
 	tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
 	if (!HeapTupleIsValid(tuple))
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index fc3a4c19e65..d8bb521f62e 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1057,7 +1057,7 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 		{
 			Oid			relid = lfirst_oid(lc);
 			HeapTuple	rftuple;
-			char		relkind;
+			Relkind		relkind;
 			char	   *relname;
 			bool		has_rowfilter;
 			bool		has_collist;
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 33e3c25a50c..8403c4850a6 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -113,7 +113,7 @@ typedef struct SubOpts
 typedef struct PublicationRelKind
 {
 	RangeVar   *rv;
-	char		relkind;
+	Relkind		relkind;
 } PublicationRelKind;
 
 static List *fetch_relation_list(WalReceiverConn *wrconn, List *publications);
@@ -821,7 +821,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
 			foreach_ptr(PublicationRelKind, pubrelinfo, pubrels)
 			{
 				Oid			relid;
-				char		relkind;
+				Relkind		relkind;
 				RangeVar   *rv = pubrelinfo->rv;
 
 				relid = RangeVarGetRelid(rv, AccessShareLock, false);
@@ -1014,7 +1014,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
 		{
 			RangeVar   *rv = pubrelinfo->rv;
 			Oid			relid;
-			char		relkind;
+			Relkind		relkind;
 
 			relid = RangeVarGetRelid(rv, AccessShareLock, false);
 			relkind = get_rel_relkind(relid);
@@ -2958,7 +2958,7 @@ fetch_relation_list(WalReceiverConn *wrconn, List *publications)
 		char	   *nspname;
 		char	   *relname;
 		bool		isnull;
-		char		relkind;
+		Relkind		relkind;
 		PublicationRelKind *relinfo = palloc_object(PublicationRelKind);
 
 		nspname = TextDatumGetCString(slot_getattr(slot, 1, &isnull));
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f976c0e5c7e..7cdc6fa2e2a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -170,7 +170,7 @@ typedef struct AlteredTableInfo
 {
 	/* Information saved before any work commences: */
 	Oid			relid;			/* Relation to work on */
-	char		relkind;		/* Its relkind */
+	Relkind		relkind;		/* Its relkind */
 	TupleDesc	oldDesc;		/* Pre-modification tuple descriptor */
 
 	/*
@@ -766,7 +766,7 @@ static void ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab,
  * ----------------------------------------------------------------
  */
 ObjectAddress
-DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
+DefineRelation(CreateStmt *stmt, Relkind relkind, Oid ownerId,
 			   ObjectAddress *typaddress, const char *queryString)
 {
 	char		relname[NAMEDATALEN];
@@ -1534,7 +1534,7 @@ void
 RemoveRelations(DropStmt *drop)
 {
 	ObjectAddresses *objects;
-	char		relkind;
+	Relkind		relkind;
 	ListCell   *cell;
 	int			flags = 0;
 	LOCKMODE	lockmode = AccessExclusiveLock;
@@ -3792,7 +3792,7 @@ SetRelationTableSpace(Relation rel,
 static void
 renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
 {
-	char		relkind = classform->relkind;
+	Relkind		relkind = classform->relkind;
 
 	if (classform->reloftype && !recursing)
 		ereport(ERROR,
@@ -4219,7 +4219,7 @@ RenameRelation(RenameStmt *stmt)
 	for (;;)
 	{
 		LOCKMODE	lockmode;
-		char		relkind;
+		Relkind		relkind;
 		bool		obj_is_index;
 
 		lockmode = is_index_stmt ? ShareUpdateExclusiveLock : AccessExclusiveLock;
@@ -7257,7 +7257,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	Form_pg_class relform;
 	Form_pg_attribute attribute;
 	int			newattnum;
-	char		relkind;
+	Relkind		relkind;
 	Expr	   *defval;
 	List	   *children;
 	ListCell   *child;
@@ -19522,7 +19522,7 @@ void
 RangeVarCallbackMaintainsTable(const RangeVar *relation,
 							   Oid relId, Oid oldRelId, void *arg)
 {
-	char		relkind;
+	Relkind		relkind;
 	AclResult	aclresult;
 
 	/* Nothing to do if the relation was not found. */
@@ -19619,7 +19619,7 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
 	HeapTuple	tuple;
 	Form_pg_class classform;
 	AclResult	aclresult;
-	char		relkind;
+	Relkind		relkind;
 
 	tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
 	if (!HeapTupleIsValid(tuple))
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 8df915f63fb..7bf826aa4aa 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -6178,7 +6178,7 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
 	TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
 	AfterTriggerEventData new_event;
 	AfterTriggerSharedData new_shared;
-	char		relkind = rel->rd_rel->relkind;
+	Relkind		relkind = rel->rd_rel->relkind;
 	int			tgtype_event;
 	int			tgtype_level;
 	int			i;
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index f5e9d369940..4981aeba196 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4351,7 +4351,7 @@ ExecModifyTable(PlanState *pstate)
 		if (operation == CMD_UPDATE || operation == CMD_DELETE ||
 			operation == CMD_MERGE)
 		{
-			char		relkind;
+			Relkind		relkind;
 			Datum		datum;
 			bool		isNull;
 
@@ -4869,7 +4869,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		if (operation == CMD_UPDATE || operation == CMD_DELETE ||
 			operation == CMD_MERGE)
 		{
-			char		relkind;
+			Relkind		relkind;
 
 			relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
 			if (relkind == RELKIND_RELATION ||
diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index 4308751f787..2e141fa3dcb 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -136,7 +136,8 @@ my @nodetag_only;
 # types that are copied by straight assignment
 my @scalar_types = qw(
   bits32 bool char double int int8 int16 int32 int64 long uint8 uint16 uint32 uint64
-  AclMode AttrNumber Cardinality Cost Index Oid RelFileNumber Selectivity Size StrategyNumber SubTransactionId TimeLineID XLogRecPtr
+  AclMode AttrNumber Cardinality Cost Index Oid RelFileNumber Relkind
+  Selectivity Size StrategyNumber SubTransactionId TimeLineID XLogRecPtr
 );
 
 # collect enum types
diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index 689840d6564..c5396116738 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -956,7 +956,7 @@ add_row_identity_columns(PlannerInfo *root, Index rtindex,
 						 Relation target_relation)
 {
 	CmdType		commandType = root->parse->commandType;
-	char		relkind = target_relation->rd_rel->relkind;
+	Relkind		relkind = target_relation->rd_rel->relkind;
 	Var		   *var;
 
 	Assert(commandType == CMD_UPDATE || commandType == CMD_DELETE || commandType == CMD_MERGE);
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index e016f64e0b3..4f1152f7f48 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -2100,7 +2100,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 		Oid			publish_as_relid = relid;
 		int			publish_ancestor_level = 0;
 		bool		am_partition = get_rel_relispartition(relid);
-		char		relkind = get_rel_relkind(relid);
+		Relkind		relkind = get_rel_relkind(relid);
 		List	   *rel_publications = NIL;
 
 		/* Reload publications if needed before use. */
diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c
index 9c680f1cb37..9a9fcda6edd 100644
--- a/src/backend/statistics/stat_utils.c
+++ b/src/backend/statistics/stat_utils.c
@@ -148,7 +148,7 @@ RangeVarCallbackForStats(const RangeVar *relation,
 	Oid			table_oid = relId;
 	HeapTuple	tuple;
 	Form_pg_class form;
-	char		relkind;
+	Relkind		relkind;
 
 	/*
 	 * If we previously locked some other index's heap, and the name we're
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 34dd6e18df5..240c663e11b 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1501,7 +1501,7 @@ ProcessUtilitySlow(ParseState *pstate,
 						foreach(lc, inheritors)
 						{
 							Oid			partrelid = lfirst_oid(lc);
-							char		relkind = get_rel_relkind(partrelid);
+							Relkind		relkind = get_rel_relkind(partrelid);
 
 							if (relkind != RELKIND_RELATION &&
 								relkind != RELKIND_MATVIEW &&
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index bc8c43b96aa..33be4c05994 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -90,7 +90,7 @@ pgstat_copy_relation_stats(Relation dst, Relation src)
 void
 pgstat_init_relation(Relation rel)
 {
-	char		relkind = rel->rd_rel->relkind;
+	Relkind		relkind = rel->rd_rel->relkind;
 
 	/*
 	 * We only count stats for relations with storage and partitioned tables
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 3a6905f9546..e4e2f18fd62 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -2170,7 +2170,7 @@ has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
 	Oid			roleid;
 	AclMode		mode;
 	AclResult	aclresult;
-	char		relkind;
+	Relkind		relkind;
 	bool		is_missing = false;
 
 	roleid = get_role_oid_or_public(NameStr(*username));
@@ -2206,7 +2206,7 @@ has_sequence_privilege_id(PG_FUNCTION_ARGS)
 	Oid			roleid;
 	AclMode		mode;
 	AclResult	aclresult;
-	char		relkind;
+	Relkind		relkind;
 	bool		is_missing = false;
 
 	roleid = GetUserId();
@@ -2269,7 +2269,7 @@ has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
 	text	   *priv_type_text = PG_GETARG_TEXT_PP(2);
 	AclMode		mode;
 	AclResult	aclresult;
-	char		relkind;
+	Relkind		relkind;
 	bool		is_missing = false;
 
 	mode = convert_sequence_priv_string(priv_type_text);
diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c
index e9db027aa2e..dff0ff2bb4c 100644
--- a/src/backend/utils/adt/partitionfuncs.c
+++ b/src/backend/utils/adt/partitionfuncs.c
@@ -33,7 +33,7 @@
 static bool
 check_rel_can_be_partition(Oid relid)
 {
-	char		relkind;
+	Relkind		relkind;
 	bool		relispartition;
 
 	/* Check if relation exists */
@@ -109,7 +109,7 @@ pg_partition_tree(PG_FUNCTION_ARGS)
 		HeapTuple	tuple;
 		Oid			parentid = InvalidOid;
 		Oid			relid = list_nth_oid(partitions, funcctx->call_cntr);
-		char		relkind = get_rel_relkind(relid);
+		Relkind		relkind = get_rel_relkind(relid);
 		int			level = 0;
 		List	   *ancestors = get_partition_ancestors(relid);
 		ListCell   *lc;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index b5a7ad9066e..ddd05ea2f86 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1060,7 +1060,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
 	if (!isnull)
 	{
 		Node	   *qual;
-		char		relkind;
+		Relkind		relkind;
 		deparse_context context;
 		deparse_namespace dpns;
 		RangeTblEntry *oldrte;
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index b924a2d900b..09fe81880e7 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2149,7 +2149,7 @@ get_rel_type_id(Oid relid)
  *
  *		Returns the relkind associated with a given relation.
  */
-char
+Relkind
 get_rel_relkind(Oid relid)
 {
 	HeapTuple	tp;
@@ -2158,9 +2158,9 @@ get_rel_relkind(Oid relid)
 	if (HeapTupleIsValid(tp))
 	{
 		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
-		char		result;
+		Relkind		result;
 
-		result = reltup->relkind;
+		result = (Relkind) reltup->relkind;
 		ReleaseSysCache(tp);
 		return result;
 	}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 6b634c9fff1..e794f4b942f 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3517,7 +3517,7 @@ RelationBuildLocalRelation(const char *relname,
 						   bool shared_relation,
 						   bool mapped_relation,
 						   char relpersistence,
-						   char relkind)
+						   Relkind relkind)
 {
 	Relation	rel;
 	MemoryContext oldcxt;
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 35d3a07915d..12f917994f6 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -2687,7 +2687,7 @@ WriteToc(ArchiveHandle *AH)
 		WriteStr(AH, te->namespace);
 		WriteStr(AH, te->tablespace);
 		WriteStr(AH, te->tableam);
-		WriteInt(AH, te->relkind);
+		WriteInt(AH, (char) te->relkind);
 		WriteStr(AH, te->owner);
 		WriteStr(AH, "false");
 
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 325b53fc9bd..cb17aab4374 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -26,6 +26,7 @@
 
 #include <time.h>
 
+#include "catalog/pg_class.h"
 #include "libpq-fe.h"
 #include "pg_backup.h"
 #include "pqexpbuffer.h"
@@ -359,7 +360,7 @@ struct _tocEntry
 	char	   *tablespace;		/* null if not in a tablespace; empty string
 								 * means use database default */
 	char	   *tableam;		/* table access method, only for TABLE tags */
-	char		relkind;		/* relation kind, only for TABLE tags */
+	Relkind		relkind;		/* relation kind, only for TABLE tags */
 	char	   *owner;
 	char	   *desc;
 	char	   *defn;
@@ -404,7 +405,7 @@ typedef struct _archiveOpts
 	const char *namespace;
 	const char *tablespace;
 	const char *tableam;
-	char		relkind;
+	Relkind		relkind;
 	const char *owner;
 	const char *description;
 	teSection	section;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index cdccccc1820..0c2cfb5abea 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -100,7 +100,7 @@ typedef struct
 typedef struct
 {
 	Oid			oid;			/* object OID */
-	char		relkind;		/* object kind */
+	Relkind		relkind;		/* object kind */
 	RelFileNumber relfilenumber;	/* object filenode */
 	Oid			toast_oid;		/* toast table OID */
 	RelFileNumber toast_relfilenumber;	/* toast table filenode */
@@ -356,7 +356,7 @@ static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
 
 static void addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx);
 static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
-static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind);
+static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, Relkind relkind);
 static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo);
 static void buildMatViewRefreshDependencies(Archive *fout);
 static void getTableDataFKConstraints(void);
@@ -3031,7 +3031,7 @@ refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo)
  *	  set up dumpable objects representing the contents of tables
  */
 static void
-getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind)
+getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, Relkind relkind)
 {
 	int			i;
 
@@ -5856,7 +5856,7 @@ collectBinaryUpgradeClassOids(Archive *fout)
 	for (int i = 0; i < nbinaryUpgradeClassOids; i++)
 	{
 		binaryUpgradeClassOids[i].oid = atooid(PQgetvalue(res, i, 0));
-		binaryUpgradeClassOids[i].relkind = *PQgetvalue(res, i, 1);
+		binaryUpgradeClassOids[i].relkind = (Relkind) *PQgetvalue(res, i, 1);
 		binaryUpgradeClassOids[i].relfilenumber = atooid(PQgetvalue(res, i, 2));
 		binaryUpgradeClassOids[i].toast_oid = atooid(PQgetvalue(res, i, 3));
 		binaryUpgradeClassOids[i].toast_relfilenumber = atooid(PQgetvalue(res, i, 4));
@@ -7121,7 +7121,7 @@ getFuncs(Archive *fout)
 static RelStatsInfo *
 getRelationStatistics(Archive *fout, DumpableObject *rel, int32 relpages,
 					  char *reltuples, int32 relallvisible,
-					  int32 relallfrozen, char relkind,
+					  int32 relallfrozen, Relkind relkind,
 					  char **indAttNames, int nindAttNames)
 {
 	if (!fout->dopt->dumpStatistics)
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 4c4b14e5fc7..99283983fac 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -215,7 +215,7 @@ typedef struct _typeInfo
 	Oid			typelem;
 	Oid			typrelid;
 	Oid			typarray;
-	char		typrelkind;		/* 'r', 'v', 'c', etc */
+	Relkind		typrelkind;		/* 'r', 'v', 'c', etc */
 	char		typtype;		/* 'b', 'c', etc */
 	bool		isArray;		/* true if auto-generated array type */
 	bool		isMultirange;	/* true if auto-generated multirange type */
@@ -307,7 +307,7 @@ typedef struct _tableInfo
 	DumpableObject dobj;
 	DumpableAcl dacl;
 	const char *rolname;
-	char		relkind;
+	Relkind		relkind;
 	char		relpersistence; /* relation persistence */
 	bool		relispopulated; /* relation is populated */
 	char		relreplident;	/* replica identifier */
@@ -452,7 +452,7 @@ typedef struct _relStatsInfo
 	char	   *reltuples;
 	int32		relallvisible;
 	int32		relallfrozen;
-	char		relkind;		/* 'r', 'm', 'i', etc */
+	Relkind		relkind;		/* 'r', 'm', 'i', etc */
 
 	/*
 	 * indAttNames/nindAttNames are populated only if the relation is an index
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 58735871c17..5920da28014 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -862,7 +862,7 @@ get_table_relkind(PGconn *con, const char *table)
 {
 	PGresult   *res;
 	char	   *val;
-	char		relkind;
+	Relkind		relkind;
 	const char *params[1] = {table};
 	const char *sql =
 		"SELECT relkind FROM pg_catalog.pg_class WHERE oid=$1::pg_catalog.regclass";
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index f02a8df8875..9d1322ae891 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -41,7 +41,7 @@ static bool describeOneTableDetails(const char *schemaname,
 									const char *relationname,
 									const char *oid,
 									bool verbose);
-static void add_tablespace_footer(printTableContent *const cont, char relkind,
+static void add_tablespace_footer(printTableContent *const cont, Relkind relkind,
 								  Oid tablespace, const bool newline);
 static void add_role_attribute(PQExpBuffer buf, const char *const str);
 static bool listTSParsersVerbose(const char *pattern);
@@ -1603,7 +1603,7 @@ describeOneTableDetails(const char *schemaname,
 	struct
 	{
 		int16		checks;
-		char		relkind;
+		Relkind		relkind;
 		bool		hasindex;
 		bool		hasrules;
 		bool		hastriggers;
@@ -3678,7 +3678,7 @@ error_return:
  * footer.
  */
 static void
-add_tablespace_footer(printTableContent *const cont, char relkind,
+add_tablespace_footer(printTableContent *const cont, Relkind relkind,
 					  Oid tablespace, const bool newline)
 {
 	/* relkinds for which we support tablespaces */
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index 0bd17b30ca7..eb7671f6ba5 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -22,6 +22,7 @@
 #include "access/amapi.h"
 #include "access/htup.h"
 #include "access/tupdesc.h"
+#include "catalog/pg_class.h"
 #include "nodes/pg_list.h"
 #include "storage/lock.h"
 
@@ -248,7 +249,7 @@ extern void *build_local_reloptions(local_relopts *relopts, Datum options,
 
 extern bytea *default_reloptions(Datum reloptions, bool validate,
 								 relopt_kind kind);
-extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
+extern bytea *heap_reloptions(Relkind relkind, Datum reloptions, bool validate);
 extern bytea *view_reloptions(Datum reloptions, bool validate);
 extern bytea *partitioned_table_reloptions(Datum reloptions, bool validate);
 extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions,
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 624c415dadb..41ad4a57391 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -16,6 +16,7 @@
 
 #include "catalog/indexing.h"
 #include "catalog/objectaddress.h"
+#include "catalog/pg_class.h"
 #include "parser/parse_node.h"
 
 
@@ -55,7 +56,7 @@ extern Relation heap_create(const char *relname,
 							RelFileNumber relfilenumber,
 							Oid accessmtd,
 							TupleDesc tupDesc,
-							char relkind,
+							Relkind relkind,
 							char relpersistence,
 							bool shared_relation,
 							bool mapped_relation,
@@ -74,7 +75,7 @@ extern Oid	heap_create_with_catalog(const char *relname,
 									 Oid accessmtd,
 									 TupleDesc tupdesc,
 									 List *cooked_constraints,
-									 char relkind,
+									 Relkind relkind,
 									 char relpersistence,
 									 bool shared_relation,
 									 bool mapped_relation,
@@ -144,7 +145,7 @@ extern const FormData_pg_attribute *SystemAttributeDefinition(AttrNumber attno);
 
 extern const FormData_pg_attribute *SystemAttributeByName(const char *attname);
 
-extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
+extern void CheckAttributeNamesTypes(TupleDesc tupdesc, Relkind relkind,
 									 int flags);
 
 extern void CheckAttributeType(const char *attname,
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index e2fe9db1161..77d444ba8d6 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -88,6 +88,6 @@ extern char *getObjectIdentityParts(const ObjectAddress *object,
 									bool missing_ok);
 extern struct ArrayType *strlist_to_textarray(List *list);
 
-extern ObjectType get_relkind_objtype(char relkind);
+extern ObjectType get_relkind_objtype(Relkind relkind);
 
 #endif							/* OBJECTADDRESS_H */
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 4afff1e8a4e..cd0d034f3d6 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -164,16 +164,19 @@ MAKE_SYSCACHE(RELNAMENSP, pg_class_relname_nsp_index, 128);
 
 #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_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;
 
 /* annoying defines for client-side C string construction */
 #define RELKIND_RELATION_STR			"'r'"
@@ -246,6 +249,6 @@ MAKE_SYSCACHE(RELNAMENSP, pg_class_relname_nsp_index, 128);
 
 #endif							/* EXPOSE_TO_CLIENT_CODE */
 
-extern int	errdetail_relkind_not_supported(char relkind);
+extern int	errdetail_relkind_not_supported(Relkind relkind);
 
 #endif							/* PG_CLASS_H */
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 368becca899..dc6a6d3d379 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -170,7 +170,7 @@ typedef enum PublicationPartOpt
 
 extern List *GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt);
 extern List *GetAllTablesPublications(void);
-extern List *GetAllPublicationRelations(char relkind, bool pubviaroot);
+extern List *GetAllPublicationRelations(Relkind relkind, bool pubviaroot);
 extern List *GetPublicationSchemas(Oid pubid);
 extern List *GetSchemaPublications(Oid schemaid);
 extern List *GetSchemaPublicationRelations(Oid schemaid,
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index ed38b311ddf..e65c2b45008 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -25,7 +25,7 @@ typedef struct AlterTableUtilityContext AlterTableUtilityContext;	/* avoid inclu
 																	 * tcop/utility.h here */
 
 
-extern ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
+extern ObjectAddress DefineRelation(CreateStmt *stmt, Relkind relkind, Oid ownerId,
 									ObjectAddress *typaddress, const char *queryString);
 
 extern TupleDesc BuildDescForRelation(const List *columns);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 646d6ced763..0d69eff8c83 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -22,6 +22,7 @@
 #ifndef PARSENODES_H
 #define PARSENODES_H
 
+#include "catalog/pg_class.h"
 #include "common/relpath.h"
 #include "nodes/bitmapset.h"
 #include "nodes/lockoptions.h"
@@ -1147,7 +1148,7 @@ typedef struct RangeTblEntry
 	/* inheritance requested? */
 	bool		inh;
 	/* relation kind (see pg_class.relkind) */
-	char		relkind pg_node_attr(query_jumble_ignore);
+	Relkind		relkind pg_node_attr(query_jumble_ignore);
 	/* lock level that query requires on the rel */
 	int			rellockmode pg_node_attr(query_jumble_ignore);
 	/* index of RTEPermissionInfo entry, or 0 */
diff --git a/src/include/replication/logicalproto.h b/src/include/replication/logicalproto.h
index 058a955e20c..e5539ffd46e 100644
--- a/src/include/replication/logicalproto.h
+++ b/src/include/replication/logicalproto.h
@@ -111,7 +111,7 @@ typedef struct LogicalRepRelation
 	char	  **attnames;		/* column names */
 	Oid		   *atttyps;		/* column types */
 	char		replident;		/* replica identity */
-	char		relkind;		/* remote relation kind */
+	Relkind		relkind;		/* remote relation kind */
 	Bitmapset  *attkeys;		/* Bitmap of key columns */
 } LogicalRepRelation;
 
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 5655aca4c14..d7e1f6132db 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -16,6 +16,7 @@
 #include "access/attnum.h"
 #include "access/cmptype.h"
 #include "access/htup.h"
+#include "catalog/pg_class.h"
 #include "nodes/pg_list.h"
 
 /* avoid including subscripting.h here */
@@ -142,7 +143,7 @@ extern Oid	get_relname_relid(const char *relname, Oid relnamespace);
 extern char *get_rel_name(Oid relid);
 extern Oid	get_rel_namespace(Oid relid);
 extern Oid	get_rel_type_id(Oid relid);
-extern char get_rel_relkind(Oid relid);
+extern Relkind get_rel_relkind(Oid relid);
 extern bool get_rel_relispartition(Oid relid);
 extern Oid	get_rel_tablespace(Oid relid);
 extern char get_rel_persistence(Oid relid);
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 2700224939a..ced2c62580a 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -15,6 +15,7 @@
 #define RELCACHE_H
 
 #include "access/tupdesc.h"
+#include "catalog/pg_class.h"
 #include "common/relpath.h"
 #include "nodes/bitmapset.h"
 
@@ -120,7 +121,7 @@ extern Relation RelationBuildLocalRelation(const char *relname,
 										   bool shared_relation,
 										   bool mapped_relation,
 										   char relpersistence,
-										   char relkind);
+										   Relkind relkind);
 
 /*
  * Routines to manage assignment of new relfilenumber to a relation
-- 
2.47.3

