>From f06f59e8f7f25406510178fbf62b59dcfd59428c Mon Sep 17 00:00:00 2001
From: Abhijit Menon-Sen <ams@2ndQuadrant.com>
Date: Tue, 1 Mar 2016 06:46:11 +0530
Subject: =?UTF-8?q?Add=20experimental=20'ALTER=20EXTENSION=20=E2=80=A6=20A?=
 =?UTF-8?q?DD=20DEPENDENT=20FUNCTION=20=E2=80=A6'=20command?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This uses the new 'x' dependency type.
---
 src/backend/commands/extension.c |  7 +++++--
 src/backend/nodes/copyfuncs.c    |  1 +
 src/backend/nodes/equalfuncs.c   |  1 +
 src/backend/parser/gram.y        | 39 ++++++++++++++++++++++++++++++++++++++-
 src/include/nodes/parsenodes.h   |  1 +
 src/include/parser/kwlist.h      |  1 +
 6 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 9d84b79..c33dca6 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2985,6 +2985,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 	ObjectAddress object;
 	Relation	relation;
 	Oid			oldExtension;
+	DependencyType deptype;
 
 	extension.classId = ExtensionRelationId;
 	extension.objectId = get_extension_oid(stmt->extname, false);
@@ -3017,6 +3018,8 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 	 */
 	oldExtension = getExtensionOfObject(object.classId, object.objectId);
 
+	deptype = stmt->deptype;
+
 	if (stmt->action > 0)
 	{
 		/*
@@ -3045,7 +3048,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 		/*
 		 * OK, add the dependency.
 		 */
-		recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
+		recordDependencyOn(&object, &extension, deptype);
 	}
 	else
 	{
@@ -3064,7 +3067,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 		 */
 		if (deleteDependencyRecordsForClass(object.classId, object.objectId,
 											ExtensionRelationId,
-											DEPENDENCY_EXTENSION) != 1)
+											deptype) != 1)
 			elog(ERROR, "unexpected number of extension dependency records");
 
 		/*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index a9e9cc3..43fc249 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3695,6 +3695,7 @@ _copyAlterExtensionContentsStmt(const AlterExtensionContentsStmt *from)
 	COPY_SCALAR_FIELD(objtype);
 	COPY_NODE_FIELD(objname);
 	COPY_NODE_FIELD(objargs);
+	COPY_SCALAR_FIELD(deptype);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index b9c3959..50646bd 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1740,6 +1740,7 @@ _equalAlterExtensionContentsStmt(const AlterExtensionContentsStmt *a, const Alte
 	COMPARE_SCALAR_FIELD(objtype);
 	COMPARE_NODE_FIELD(objname);
 	COMPARE_NODE_FIELD(objargs);
+	COMPARE_SCALAR_FIELD(deptype);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b307b48..4a887d0 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -577,7 +577,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 	CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
 
 	DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
-	DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC
+	DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DEPENDENT DESC
 	DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
 
 	EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT
@@ -3935,6 +3935,7 @@ AlterExtensionContentsStmt:
 					n->objtype = OBJECT_AGGREGATE;
 					n->objname = $6;
 					n->objargs = extractAggrArgTypes($7);
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop CAST '(' Typename AS Typename ')'
@@ -3945,6 +3946,7 @@ AlterExtensionContentsStmt:
 					n->objtype = OBJECT_CAST;
 					n->objname = list_make1($7);
 					n->objargs = list_make1($9);
+					n->deptype = 'e';
 					$$ = (Node *) n;
 				}
 			| ALTER EXTENSION name add_drop COLLATION any_name
@@ -3954,6 +3956,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_COLLATION;
 					n->objname = $6;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop CONVERSION_P any_name
@@ -3963,6 +3966,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_CONVERSION;
 					n->objname = $6;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop DOMAIN_P Typename
@@ -3972,6 +3976,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_DOMAIN;
 					n->objname = list_make1($6);
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop FUNCTION function_with_argtypes
@@ -3982,6 +3987,7 @@ AlterExtensionContentsStmt:
 					n->objtype = OBJECT_FUNCTION;
 					n->objname = $6->funcname;
 					n->objargs = $6->funcargs;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop opt_procedural LANGUAGE name
@@ -3991,6 +3997,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_LANGUAGE;
 					n->objname = list_make1(makeString($7));
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop OPERATOR any_operator oper_argtypes
@@ -4001,6 +4008,7 @@ AlterExtensionContentsStmt:
 					n->objtype = OBJECT_OPERATOR;
 					n->objname = $6;
 					n->objargs = $7;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING access_method
@@ -4010,6 +4018,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_OPCLASS;
 					n->objname = lcons(makeString($9), $7);
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING access_method
@@ -4019,6 +4028,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_OPFAMILY;
 					n->objname = lcons(makeString($9), $7);
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop SCHEMA name
@@ -4028,6 +4038,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_SCHEMA;
 					n->objname = list_make1(makeString($6));
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop EVENT TRIGGER name
@@ -4037,6 +4048,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_EVENT_TRIGGER;
 					n->objname = list_make1(makeString($7));
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TABLE any_name
@@ -4046,6 +4058,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_TABLE;
 					n->objname = $6;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TEXT_P SEARCH PARSER any_name
@@ -4055,6 +4068,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_TSPARSER;
 					n->objname = $8;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TEXT_P SEARCH DICTIONARY any_name
@@ -4064,6 +4078,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_TSDICTIONARY;
 					n->objname = $8;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TEXT_P SEARCH TEMPLATE any_name
@@ -4073,6 +4088,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_TSTEMPLATE;
 					n->objname = $8;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TEXT_P SEARCH CONFIGURATION any_name
@@ -4082,6 +4098,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_TSCONFIGURATION;
 					n->objname = $8;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop SEQUENCE any_name
@@ -4091,6 +4108,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_SEQUENCE;
 					n->objname = $6;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop VIEW any_name
@@ -4100,6 +4118,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_VIEW;
 					n->objname = $6;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop MATERIALIZED VIEW any_name
@@ -4109,6 +4128,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_MATVIEW;
 					n->objname = $7;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop FOREIGN TABLE any_name
@@ -4118,6 +4138,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_FOREIGN_TABLE;
 					n->objname = $7;
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop FOREIGN DATA_P WRAPPER name
@@ -4127,6 +4148,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_FDW;
 					n->objname = list_make1(makeString($8));
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop SERVER name
@@ -4136,6 +4158,7 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_FOREIGN_SERVER;
 					n->objname = list_make1(makeString($6));
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TRANSFORM FOR Typename LANGUAGE name
@@ -4146,6 +4169,7 @@ AlterExtensionContentsStmt:
 					n->objtype = OBJECT_TRANSFORM;
 					n->objname = list_make1($7);
 					n->objargs = list_make1(makeString($9));
+					n->deptype = 'e';
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop TYPE_P Typename
@@ -4155,6 +4179,18 @@ AlterExtensionContentsStmt:
 					n->action = $4;
 					n->objtype = OBJECT_TYPE;
 					n->objname = list_make1($6);
+					n->deptype = 'e';
+					$$ = (Node *)n;
+				}
+			| ALTER EXTENSION name add_drop DEPENDENT FUNCTION function_with_argtypes
+				{
+					AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
+					n->extname = $3;
+					n->action = $4;
+					n->objtype = OBJECT_FUNCTION;
+					n->objname = $7->funcname;
+					n->objargs = $7->funcargs;
+					n->deptype = 'x';
 					$$ = (Node *)n;
 				}
 		;
@@ -13706,6 +13742,7 @@ unreserved_keyword:
 			| DELETE_P
 			| DELIMITER
 			| DELIMITERS
+			| DEPENDENT
 			| DICTIONARY
 			| DISABLE_P
 			| DISCARD
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 2fd0629..7305559 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1930,6 +1930,7 @@ typedef struct AlterExtensionContentsStmt
 	ObjectType	objtype;		/* Object's type */
 	List	   *objname;		/* Qualified name of the object */
 	List	   *objargs;		/* Arguments if needed (eg, for functions) */
+	char		deptype;		/* Dependency type: 'e' or 'x' */
 } AlterExtensionContentsStmt;
 
 /* ----------------------
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 6e1e820..5b84d34 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -125,6 +125,7 @@ PG_KEYWORD("definer", DEFINER, UNRESERVED_KEYWORD)
 PG_KEYWORD("delete", DELETE_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD)
 PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD)
+PG_KEYWORD("dependent", DEPENDENT, UNRESERVED_KEYWORD)
 PG_KEYWORD("desc", DESC, RESERVED_KEYWORD)
 PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD)
 PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD)
-- 
2.1.4

