From bb58da8003a276ece047f5c9b1acab3966f09167 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Tue, 13 Feb 2018 12:13:39 +0900
Subject: [PATCH 3/4] Refactor format_type APIs to be more modular

As of now, format type names can be generated using multiple APIs which
share much:
- format_type_be, which is used mainly for error messages.
- format_type_be_qualified, which qualifies the type name.
- format_type_with_typemod, which allows a non-default typemod to be
defined.
- format_type_with_typemod_qualified, which allows a non default typemod
to be specified and qualifies the type name.  This is used only by
postgres_fdw.

This patch removes format_type_with_typemod_qualified and makes
format_type_internal publicly available with a set of flags that callers
can use to control how a type name is generated.
format_type_be_qualified is also localized, and could be plugged off,
but this is left for future consideration.
---
 contrib/postgres_fdw/deparse.c      | 10 ++++---
 src/backend/utils/adt/format_type.c | 60 ++++++++++++++++++-------------------
 src/include/utils/builtins.h        | 11 +++++--
 3 files changed, 44 insertions(+), 37 deletions(-)

diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index f4b38c65ac..02894a7e35 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -854,10 +854,12 @@ foreign_expr_walker(Node *node,
 static char *
 deparse_type_name(Oid type_oid, int32 typemod)
 {
-	if (is_builtin(type_oid))
-		return format_type_with_typemod(type_oid, typemod);
-	else
-		return format_type_with_typemod_qualified(type_oid, typemod);
+	uint8 flags = FORMAT_TYPE_TYPEMOD_GIVEN;
+
+	if (!is_builtin(type_oid))
+		flags |= FORMAT_TYPE_FORCE_QUALIFY;
+
+	return format_type_extended(type_oid, typemod, flags);
 }
 
 /*
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index de3da3607a..58eb220ff8 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -28,9 +28,6 @@
 
 #define MAX_INT32_LEN 11
 
-static char *format_type_internal(Oid type_oid, int32 typemod,
-					 bool typemod_given, bool allow_invalid,
-					 bool force_qualify);
 static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
 
 
@@ -74,11 +71,12 @@ format_type(PG_FUNCTION_ARGS)
 	type_oid = PG_GETARG_OID(0);
 
 	if (PG_ARGISNULL(1))
-		result = format_type_internal(type_oid, -1, false, true, false);
+		result = format_type_extended(type_oid, -1, FORMAT_TYPE_ALLOW_INVALID);
 	else
 	{
 		typemod = PG_GETARG_INT32(1);
-		result = format_type_internal(type_oid, typemod, true, true, false);
+		result = format_type_extended(type_oid, typemod,
+					  FORMAT_TYPE_TYPEMOD_GIVEN | FORMAT_TYPE_ALLOW_INVALID);
 	}
 
 	PG_RETURN_TEXT_P(cstring_to_text(result));
@@ -93,7 +91,7 @@ format_type(PG_FUNCTION_ARGS)
 char *
 format_type_be(Oid type_oid)
 {
-	return format_type_internal(type_oid, -1, false, false, false);
+	return format_type_extended(type_oid, -1, 0);
 }
 
 /*
@@ -103,7 +101,7 @@ format_type_be(Oid type_oid)
 char *
 format_type_be_qualified(Oid type_oid)
 {
-	return format_type_internal(type_oid, -1, false, false, true);
+	return format_type_extended(type_oid, -1, FORMAT_TYPE_FORCE_QUALIFY);
 }
 
 /*
@@ -112,41 +110,40 @@ format_type_be_qualified(Oid type_oid)
 char *
 format_type_with_typemod(Oid type_oid, int32 typemod)
 {
-	return format_type_internal(type_oid, typemod, true, false, false);
+	return format_type_extended(type_oid, typemod, FORMAT_TYPE_TYPEMOD_GIVEN);
 }
 
 /*
- * This version allows a nondefault typemod to be specified, and forces
- * qualification of normal type names.
+ * format_type_extended
+ *
+ * Workhouse to generate a type name, controlled by the following set of
+ * options:
+ * - FORMAT_TYPE_TYPEMOD_GIVEN, which allows a non default typemod to be
+ *   specified.
+ * - FORMAT_TYPE_ALLOW_INVALID, which does not generate an error for an
+ *   invalid type and returns a result back to the caller.
+ * - FORMAT_TYPE_FORCE_QUALIFY, which forces the qualification of normal
+ *   type names.
  */
 char *
-format_type_with_typemod_qualified(Oid type_oid, int32 typemod)
-{
-	return format_type_internal(type_oid, typemod, true, false, true);
-}
-
-/*
- * Common workhorse.
- */
-static char *
-format_type_internal(Oid type_oid, int32 typemod,
-					 bool typemod_given, bool allow_invalid,
-					 bool force_qualify)
+format_type_extended(Oid type_oid, int32 typemod,
+					 uint8 flags)
 {
-	bool		with_typemod = typemod_given && (typemod >= 0);
+	bool		with_typemod = (flags & FORMAT_TYPE_TYPEMOD_GIVEN) != 0 &&
+							   (typemod >= 0);
 	HeapTuple	tuple;
 	Form_pg_type typeform;
 	Oid			array_base_type;
 	bool		is_array;
 	char	   *buf;
 
-	if (type_oid == InvalidOid && allow_invalid)
+	if (type_oid == InvalidOid && (flags & FORMAT_TYPE_ALLOW_INVALID) != 0)
 		return pstrdup("-");
 
 	tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
 	if (!HeapTupleIsValid(tuple))
 	{
-		if (allow_invalid)
+		if ((flags & FORMAT_TYPE_ALLOW_INVALID) != 0)
 			return pstrdup("???");
 		else
 			elog(ERROR, "cache lookup failed for type %u", type_oid);
@@ -170,7 +167,7 @@ format_type_internal(Oid type_oid, int32 typemod,
 		tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(array_base_type));
 		if (!HeapTupleIsValid(tuple))
 		{
-			if (allow_invalid)
+			if ((flags & FORMAT_TYPE_ALLOW_INVALID) != 0)
 				return pstrdup("???[]");
 			else
 				elog(ERROR, "cache lookup failed for type %u", type_oid);
@@ -200,7 +197,7 @@ format_type_internal(Oid type_oid, int32 typemod,
 		case BITOID:
 			if (with_typemod)
 				buf = printTypmod("bit", typemod, typeform->typmodout);
-			else if (typemod_given)
+			else if ((flags & FORMAT_TYPE_TYPEMOD_GIVEN) != 0)
 			{
 				/*
 				 * bit with typmod -1 is not the same as BIT, which means
@@ -219,7 +216,7 @@ format_type_internal(Oid type_oid, int32 typemod,
 		case BPCHAROID:
 			if (with_typemod)
 				buf = printTypmod("character", typemod, typeform->typmodout);
-			else if (typemod_given)
+			else if ((flags & FORMAT_TYPE_TYPEMOD_GIVEN) != 0)
 			{
 				/*
 				 * bpchar with typmod -1 is not the same as CHARACTER, which
@@ -319,7 +316,8 @@ format_type_internal(Oid type_oid, int32 typemod,
 		char	   *nspname;
 		char	   *typname;
 
-		if (!force_qualify && TypeIsVisible(type_oid))
+		if ((flags & FORMAT_TYPE_FORCE_QUALIFY) == 0 &&
+			TypeIsVisible(type_oid))
 			nspname = NULL;
 		else
 			nspname = get_namespace_name_or_temp(typeform->typnamespace);
@@ -437,8 +435,8 @@ oidvectortypes(PG_FUNCTION_ARGS)
 
 	for (num = 0; num < numargs; num++)
 	{
-		char	   *typename = format_type_internal(oidArray->values[num], -1,
-													false, true, false);
+		char	   *typename = format_type_extended(oidArray->values[num], -1,
+													FORMAT_TYPE_ALLOW_INVALID);
 		size_t		slen = strlen(typename);
 
 		if (left < (slen + 2))
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 8bb57c5829..27aa67c3fa 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -112,11 +112,18 @@ extern void clean_ipv6_addr(int addr_family, char *addr);
 extern Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS);
 
 /* format_type.c */
+extern char *format_type_extended(Oid type_oid, int32 typemod, uint8 flags);
+extern int32 type_maximum_size(Oid type_oid, int32 typemod);
+
+/* Control flags for format_type_extended */
+#define FORMAT_TYPE_TYPEMOD_GIVEN	0x01	/* typemod defined by caller */
+#define FORMAT_TYPE_ALLOW_INVALID	0x02	/* allow invalid types */
+#define FORMAT_TYPE_FORCE_QUALIFY	0x04	/* force qualification of type */
+
+/* Those declarations are deprecated, and kept for compatibility */
 extern char *format_type_be(Oid type_oid);
 extern char *format_type_be_qualified(Oid type_oid);
 extern char *format_type_with_typemod(Oid type_oid, int32 typemod);
-extern char *format_type_with_typemod_qualified(Oid type_oid, int32 typemod);
-extern int32 type_maximum_size(Oid type_oid, int32 typemod);
 
 /* quote.c */
 extern char *quote_literal_cstr(const char *rawstr);
-- 
2.16.1

