From d1878729d70c8f9fd27df3ed73474a2b7dc6e6f8 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 13 Mar 2015 14:17:58 -0300
Subject: [PATCH 28/37] infrastructure for ALTER OPERATOR FAMILY

---
 src/backend/commands/event_trigger.c | 39 +++++++++++++++++++++++++++++++++++-
 src/backend/commands/opclasscmds.c   | 15 +-------------
 src/backend/tcop/deparse_utility.c   |  6 +++++-
 src/include/catalog/opfam_internal.h | 28 ++++++++++++++++++++++++++
 src/include/commands/event_trigger.h |  2 ++
 src/include/tcop/deparse_utility.h   | 11 +++++++++-
 6 files changed, 84 insertions(+), 17 deletions(-)
 create mode 100644 src/include/catalog/opfam_internal.h

diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 3c57951..9b51bf3 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -20,6 +20,7 @@
 #include "catalog/objectaccess.h"
 #include "catalog/pg_event_trigger.h"
 #include "catalog/pg_namespace.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
@@ -1855,6 +1856,37 @@ EventTriggerStashGrant(InternalGrant *istmt)
 	MemoryContextSwitchTo(oldcxt);
 }
 
+/*
+ * EventTriggerStashAlterOpFam
+ * 		Save data about an ALTER OPERATOR FAMILY ADD/DROP command being
+ * 		executed
+ */
+void
+EventTriggerStashAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
+							List *operators, List *procedures)
+{
+	MemoryContext	oldcxt;
+	StashedCommand *stashed;
+
+	if (currentEventTriggerState->commandCollectionInhibited)
+		return;
+
+	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+	stashed = palloc(sizeof(StashedCommand));
+	stashed->type = SCT_AlterOpFamily;
+	stashed->in_extension = creating_extension;
+	stashed->d.opfam.opfamOid = opfamoid;
+	stashed->d.opfam.operators = operators;		/* XXX prolly need to copy */
+	stashed->d.opfam.procedures = procedures;	/* XXX ditto */
+	stashed->parsetree = copyObject(stmt);
+
+	currentEventTriggerState->stash = lappend(currentEventTriggerState->stash,
+											  stashed);
+
+	MemoryContextSwitchTo(oldcxt);
+}
+
 Datum
 pg_event_trigger_get_creation_commands(PG_FUNCTION_ARGS)
 {
@@ -1934,7 +1966,8 @@ pg_event_trigger_get_creation_commands(PG_FUNCTION_ARGS)
 		MemSet(nulls, 0, sizeof(nulls));
 
 		if (cmd->type == SCT_Simple ||
-			cmd->type == SCT_AlterTable)
+			cmd->type == SCT_AlterTable ||
+			cmd->type == SCT_AlterOpFamily)
 		{
 			const char *tag;
 			char	   *identity;
@@ -1947,6 +1980,10 @@ pg_event_trigger_get_creation_commands(PG_FUNCTION_ARGS)
 				ObjectAddressSet(addr,
 								 cmd->d.alterTable.classId,
 								 cmd->d.alterTable.objectId);
+			else if (cmd->type == SCT_AlterOpFamily)
+				ObjectAddressSet(addr,
+								 OperatorFamilyRelationId,
+								 cmd->d.opfam.opfamOid);
 
 			tag = CreateCommandTag(cmd->parsetree);
 
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index c327cc0..d5ca502 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -25,6 +25,7 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
+#include "catalog/opfam_internal.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_namespace.h"
@@ -47,20 +48,6 @@
 #include "utils/tqual.h"
 
 
-/*
- * We use lists of this struct type to keep track of both operators and
- * procedures while building or adding to an opfamily.
- */
-typedef struct
-{
-	Oid			object;			/* operator or support proc's OID */
-	int			number;			/* strategy or support proc number */
-	Oid			lefttype;		/* lefttype */
-	Oid			righttype;		/* righttype */
-	Oid			sortfamily;		/* ordering operator's sort opfamily, or 0 */
-} OpFamilyMember;
-
-
 static void AlterOpFamilyAdd(List *opfamilyname, Oid amoid, Oid opfamilyoid,
 				 int maxOpNumber, int maxProcNumber,
 				 List *items);
diff --git a/src/backend/tcop/deparse_utility.c b/src/backend/tcop/deparse_utility.c
index 9f05d0e..195b06f 100644
--- a/src/backend/tcop/deparse_utility.c
+++ b/src/backend/tcop/deparse_utility.c
@@ -6299,7 +6299,8 @@ deparse_simple_command(StashedCommand *cmd)
 			break;
 
 		case T_AlterOpFamilyStmt:
-			elog(ERROR, "unimplemented deparse of %s", CreateCommandTag(parsetree));
+			/* handled elsewhere */
+			elog(ERROR, "unexpected command type %s", CreateCommandTag(parsetree));
 			break;
 
 		case T_AlterTSDictionaryStmt:
@@ -6422,6 +6423,9 @@ deparse_utility_command(StashedCommand *cmd)
 		case SCT_Grant:
 			tree = deparse_GrantStmt(cmd);
 			break;
+		case SCT_AlterOpFamily:
+			tree = deparse_AlterOpFamily(cmd);
+			break;
 		default:
 			elog(ERROR, "unexpected deparse node type %d", cmd->type);
 	}
diff --git a/src/include/catalog/opfam_internal.h b/src/include/catalog/opfam_internal.h
new file mode 100644
index 0000000..f01dcbe
--- /dev/null
+++ b/src/include/catalog/opfam_internal.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * opfam_internal.h
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/opfam_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OPFAM_INTERNAL_H
+#define OPFAM_INTERNAL_H
+
+/*
+ * We use lists of this struct type to keep track of both operators and
+ * procedures while building or adding to an opfamily.
+ */
+typedef struct
+{
+	Oid			object;			/* operator or support proc's OID */
+	int			number;			/* strategy or support proc number */
+	Oid			lefttype;		/* lefttype */
+	Oid			righttype;		/* righttype */
+	Oid			sortfamily;		/* ordering operator's sort opfamily, or 0 */
+} OpFamilyMember;
+
+#endif		/* OPFAM_INTERNAL_H */
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 932630f..a8435e3 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -74,5 +74,7 @@ extern void EventTriggerAlterTableStashSubcmd(Node *subcmd, Oid relid,
 extern void EventTriggerAlterTableEnd(void);
 
 extern void EventTriggerStashGrant(InternalGrant *istmt);
+extern void EventTriggerStashAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
+							List *operators, List *procedures);
 
 #endif   /* EVENT_TRIGGER_H */
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index 7f70ede..6aa5fa5 100644
--- a/src/include/tcop/deparse_utility.h
+++ b/src/include/tcop/deparse_utility.h
@@ -29,7 +29,8 @@ typedef enum StashedCommandType
 {
 	SCT_Simple,
 	SCT_AlterTable,
-	SCT_Grant
+	SCT_Grant,
+	SCT_AlterOpFamily
 } StashedCommandType;
 
 /*
@@ -71,6 +72,14 @@ typedef struct StashedCommand
 			InternalGrant *istmt;
 			const char *type;
 		} grant;
+
+		/* ALTER OPERATOR FAMILY */
+		struct
+		{
+			Oid		opfamOid;
+			List   *operators;
+			List   *procedures;
+		} opfam;
 	} d;
 } StashedCommand;
 
-- 
2.1.4

