From 22dcac16ad0dceca1bb772a32568ed9d5d2f1ed6 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 10 Feb 2015 14:09:51 -0300
Subject: [PATCH 33/44] deparse: support CREATE CAST

---
 src/backend/tcop/deparse_utility.c | 78 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 77 insertions(+), 1 deletion(-)

diff --git a/src/backend/tcop/deparse_utility.c b/src/backend/tcop/deparse_utility.c
index 75e3c31..5ea9622 100644
--- a/src/backend/tcop/deparse_utility.c
+++ b/src/backend/tcop/deparse_utility.c
@@ -33,6 +33,7 @@
 #include "catalog/namespace.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
@@ -4351,6 +4352,81 @@ deparse_CreateConversion(Oid objectId, Node *parsetree)
 }
 
 static ObjTree *
+deparse_CreateCastStmt(Oid objectId, Node *parsetree)
+{
+	CreateCastStmt *node = (CreateCastStmt *) parsetree;
+	Relation	castrel;
+	HeapTuple	castTup;
+	Form_pg_cast castForm;
+	ObjTree	   *createCast;
+	char	   *context;
+
+	castrel = heap_open(CastRelationId, AccessShareLock);
+	castTup = get_catalog_object_by_oid(castrel, objectId);
+	if (!HeapTupleIsValid(castTup))
+		elog(ERROR, "cache lookup failed for cast with OID %u", objectId);
+	castForm = (Form_pg_cast) GETSTRUCT(castTup);
+
+	createCast = new_objtree_VA("CREATE CAST (%{sourcetype}T AS %{targettype}T) %{mechanism}s %{context}s",
+								2, "sourcetype", ObjTypeObject,
+								new_objtree_for_type(castForm->castsource, -1),
+								"targettype", ObjTypeObject,
+								new_objtree_for_type(castForm->casttarget, -1));
+
+	if (node->inout)
+		append_string_object(createCast, "mechanism", "WITH INOUT");
+	else if (node->func == NULL)
+		append_string_object(createCast, "mechanism", "WITHOUT FUNCTION");
+	else
+	{
+		ObjTree	   *tmp;
+		StringInfoData func;
+		HeapTuple	funcTup;
+		Form_pg_proc funcForm;
+		int			i;
+
+		funcTup = SearchSysCache1(PROCOID, castForm->castfunc);
+		funcForm = (Form_pg_proc) GETSTRUCT(funcTup);
+
+		initStringInfo(&func);
+		appendStringInfo(&func, "%s(",
+						quote_qualified_identifier(get_namespace_name(funcForm->pronamespace),
+												   NameStr(funcForm->proname)));
+		for (i = 0; i < funcForm->pronargs; i++)
+			appendStringInfoString(&func,
+								   format_type_be_qualified(funcForm->proargtypes.values[i]));
+		appendStringInfoChar(&func, ')');
+
+		tmp = new_objtree_VA("WITH FUNCTION %{castfunction}s", 1,
+							 "castfunction", ObjTypeString, func.data);
+		append_object_object(createCast, "mechanism", tmp);
+
+		ReleaseSysCache(funcTup);
+	}
+
+	switch (node->context)
+	{
+		case COERCION_IMPLICIT:
+			context = "AS IMPLICIT";
+			break;
+		case COERCION_ASSIGNMENT:
+			context = "AS ASSIGNMENT";
+			break;
+		case COERCION_EXPLICIT:
+			context = "";
+			break;
+		default:
+			elog(ERROR, "invalid coercion code %c", node->context);
+			return NULL;	/* keep compiler quiet */
+	}
+	append_string_object(createCast, "context", context);
+
+	heap_close(castrel, AccessShareLock);
+
+	return createCast;
+}
+
+static ObjTree *
 deparse_CreateOpFamily(Oid objectId, Node *parsetree)
 {
 	HeapTuple   opfTup;
@@ -5246,7 +5322,7 @@ deparse_simple_command(StashedCommand *cmd)
 			break;
 
 		case T_CreateCastStmt:
-			elog(ERROR, "unimplemented deparse of %s", CreateCommandTag(parsetree));
+			command = deparse_CreateCastStmt(objectId, parsetree);
 			break;
 
 		case T_CreateOpClassStmt:
-- 
2.1.4

