>From ccbb04379d61cdbf0626f8aba8f13c2cf664de7c Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 24 Feb 2015 12:35:49 -0300
Subject: [PATCH 39/44] fixup! deparse: infrastructure needed for command
 deparsing

Change is_array to typarray (per Andres).  Also, fix handling of
timestamp, timestamptz without typmods, and arrays of all those special
types.
---
 src/backend/tcop/deparse_utility.c  |  6 +++---
 src/backend/utils/adt/ddl_json.c    |  4 ++--
 src/backend/utils/adt/format_type.c | 42 ++++++++++++++++++++++++-------------
 3 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/src/backend/tcop/deparse_utility.c b/src/backend/tcop/deparse_utility.c
index d31cb5b..e9d0a28 100644
--- a/src/backend/tcop/deparse_utility.c
+++ b/src/backend/tcop/deparse_utility.c
@@ -549,10 +549,10 @@ new_objtree_for_type(Oid typeId, int32 typmod)
 	char	   *typnsp;
 	char	   *typename;
 	char	   *typmodstr;
-	bool		is_array;
+	bool		typarray;
 
 	format_type_detailed(typeId, typmod,
-						 &typnspid, &typename, &typmodstr, &is_array);
+						 &typnspid, &typename, &typmodstr, &typarray);
 
 	if (!OidIsValid(typnspid))
 		typnsp = pstrdup("");
@@ -566,7 +566,7 @@ new_objtree_for_type(Oid typeId, int32 typmod)
 	append_string_object(typeParam, "schemaname", typnsp);
 	append_string_object(typeParam, "typename", typename);
 	append_string_object(typeParam, "typmod", typmodstr);
-	append_bool_object(typeParam, "is_array", is_array);
+	append_bool_object(typeParam, "typarray", typarray);
 
 	return typeParam;
 }
diff --git a/src/backend/utils/adt/ddl_json.c b/src/backend/utils/adt/ddl_json.c
index 5b0326c..9f6f42e 100644
--- a/src/backend/utils/adt/ddl_json.c
+++ b/src/backend/utils/adt/ddl_json.c
@@ -335,14 +335,14 @@ expand_jsonval_typename(StringInfo buf, JsonbValue *jsonval)
 	typmodstr = find_string_in_jsonbcontainer(jsonval->val.binary.data,
 											  "typmod", true, NULL);
 	is_array = find_bool_in_jsonbcontainer(jsonval->val.binary.data,
-										   "is_array");
+										   "typarray");
 	switch (is_array)
 	{
 		default:
 		case tv_absent:
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("missing is_array element")));
+					 errmsg("missing typarray element")));
 			break;
 		case tv_true:
 			array_decor = "[]";
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index dbf6b60..5eb13ff 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -332,25 +332,21 @@ format_type_internal(Oid type_oid, int32 typemod,
  *
  * - nspid is the schema OID.  For certain SQL-standard types which have weird
  *   typmod rules, we return InvalidOid; caller is expected to not schema-
- *   qualify the name nor add quotes to the type name.
+ *   qualify the name nor add quotes to the type name in this case.
  *
  * - typename is set to the type name, without quotes
  *
  * - typmod is set to the typemod, if any, as a string with parens
  *
- * - is_array indicates whether []s must be added
+ * - typarray indicates whether []s must be added
  *
- * Also, we don't try to decode type names to their standard-mandated names,
- * except in the cases of unusual typmod rules, as specified above.
- *
- * XXX there is a lot of code duplication between this routine and
- * format_type_internal.  (One thing that doesn't quite match is the whole
- * allow_invalid business.)
+ * We don't try to decode type names to their standard-mandated names, except
+ * in the cases of types with unusual typmod rules.
  */
 void
 format_type_detailed(Oid type_oid, int32 typemod,
 					 Oid *nspid, char **typname, char **typemodstr,
-					 bool *is_array)
+					 bool *typarray)
 {
 	HeapTuple	tuple;
 	Form_pg_type typeform;
@@ -369,14 +365,22 @@ format_type_detailed(Oid type_oid, int32 typemod,
 		type_oid == TIMESTAMPOID ||
 		type_oid == TIMESTAMPTZOID)
 	{
+		*typarray = false;
+
+peculiar_typmod:
 		switch (type_oid)
 		{
 			case INTERVALOID:
 				*typname = pstrdup("INTERVAL");
 				break;
-			case TIMESTAMPOID:
 			case TIMESTAMPTZOID:
-				/* the TZ part is added by typmod */
+				if (typemod < 0)
+				{
+					*typname = pstrdup("TIMESTAMP WITH TIME ZONE");
+					break;
+				}
+				/* otherwise, WITH TZ is added by typmod, so fall through */
+			case TIMESTAMPOID:
 				*typname = pstrdup("TIMESTAMP");
 				break;
 		}
@@ -387,8 +391,6 @@ format_type_detailed(Oid type_oid, int32 typemod,
 		else
 			*typemodstr = pstrdup("");
 
-		*is_array = false;
-
 		ReleaseSysCache(tuple);
 		return;
 	}
@@ -410,10 +412,20 @@ format_type_detailed(Oid type_oid, int32 typemod,
 
 		typeform = (Form_pg_type) GETSTRUCT(tuple);
 		type_oid = array_base_type;
-		*is_array = true;
+		*typarray = true;
+
+		/*
+		 * If it's an array of one of the types with special typmod rules,
+		 * have the element type be processed as above, but now with typarray
+		 * set to true.
+		 */
+		if (type_oid == INTERVALOID ||
+			type_oid == TIMESTAMPTZOID ||
+			type_oid == TIMESTAMPOID)
+			goto peculiar_typmod;
 	}
 	else
-		*is_array = false;
+		*typarray = false;
 
 	*nspid = typeform->typnamespace;
 	*typname = pstrdup(NameStr(typeform->typname));
-- 
2.1.4

