From ca25c97a62d8ae0722e17b4b5d975c7adc885601 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Mon, 19 Sep 2016 12:00:00 -0400
Subject: [PATCH 7/7] Pass operators around with FuncWithArgs as well

This unifies the operator handling with the previous changes for
functions and aggregates.
---
 doc/src/sgml/ref/drop_operator.sgml |  2 +-
 src/backend/catalog/objectaddress.c | 38 +++++++++---------
 src/backend/commands/dropcmds.c     | 13 ++++---
 src/backend/commands/opclasscmds.c  | 18 +--------
 src/backend/commands/operatorcmds.c |  5 +--
 src/backend/nodes/copyfuncs.c       |  1 -
 src/backend/nodes/equalfuncs.c      |  1 -
 src/backend/parser/gram.y           | 77 +++++++++++++++++++++----------------
 src/backend/parser/parse_oper.c     | 25 ++++++------
 src/include/nodes/parsenodes.h      |  3 +-
 src/include/parser/parse_oper.h     |  5 +--
 11 files changed, 90 insertions(+), 98 deletions(-)

diff --git a/doc/src/sgml/ref/drop_operator.sgml b/doc/src/sgml/ref/drop_operator.sgml
index 13dd974..e196547 100644
--- a/doc/src/sgml/ref/drop_operator.sgml
+++ b/doc/src/sgml/ref/drop_operator.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-DROP OPERATOR [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ( { <replaceable class="PARAMETER">left_type</replaceable> | NONE } , { <replaceable class="PARAMETER">right_type</replaceable> | NONE } ) [ CASCADE | RESTRICT ]
+DROP OPERATOR [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ( { <replaceable class="PARAMETER">left_type</replaceable> | NONE } , { <replaceable class="PARAMETER">right_type</replaceable> | NONE } ) [, ...] [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index a682460..c5d2e60 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -836,15 +836,13 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
 					break;
 				}
 			case OBJECT_OPERATOR:
-				Assert(list_length(objargs) == 2);
-				address.classId = OperatorRelationId;
-				address.objectId =
-					LookupOperNameTypeNames(NULL, objname,
-											(TypeName *) linitial(objargs),
-											(TypeName *) lsecond(objargs),
-											missing_ok, -1);
-				address.objectSubId = 0;
-				break;
+				{
+					FuncWithArgs *fwa = (FuncWithArgs *) linitial(objname);
+					address.classId = OperatorRelationId;
+					address.objectId = LookupOperWithArgs(fwa, missing_ok);
+					address.objectSubId = 0;
+					break;
+				}
 			case OBJECT_COLLATION:
 				address.classId = CollationRelationId;
 				address.objectId = get_collation_oid(objname, missing_ok);
@@ -1996,16 +1994,6 @@ pg_get_object_address(PG_FUNCTION_ARGS)
 		args = textarray_to_strvaluelist(argsarr);
 	}
 
-	if (type == OBJECT_FUNCTION || type == OBJECT_AGGREGATE)
-	{
-		FuncWithArgs *fwa = makeNode(FuncWithArgs);
-
-		fwa->funcname = name;
-		fwa->funcargs = args;
-		name = list_make1(fwa);
-		args = NIL;
-	}
-
 	/*
 	 * get_object_name is pretty sensitive to the length its input lists;
 	 * check that they're what it wants.
@@ -2046,6 +2034,16 @@ pg_get_object_address(PG_FUNCTION_ARGS)
 			break;
 	}
 
+	if (type == OBJECT_FUNCTION || type == OBJECT_AGGREGATE || type == OBJECT_OPERATOR)
+	{
+		FuncWithArgs *fwa = makeNode(FuncWithArgs);
+
+		fwa->funcname = name;
+		fwa->funcargs = args;
+		name = list_make1(fwa);
+		args = NIL;
+	}
+
 	addr = get_object_address(type, name, args,
 							  &relation, AccessShareLock, false);
 
@@ -2119,7 +2117,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 		case OBJECT_OPERATOR:
 			if (!pg_oper_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
-							   NameListToString(objname));
+							   NameListToString(((FuncWithArgs *) linitial(objname))->funcname));
 			break;
 		case OBJECT_SCHEMA:
 			if (!pg_namespace_ownercheck(address.objectId, roleid))
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index 32fe2e9..6c9786e 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -73,7 +73,7 @@ RemoveObjects(DropStmt *stmt)
 			objargs = lfirst(cell2);
 		}
 
-		if (stmt->removeType == OBJECT_AGGREGATE || stmt->removeType == OBJECT_FUNCTION)
+		if (stmt->removeType == OBJECT_AGGREGATE || stmt->removeType == OBJECT_FUNCTION || stmt->removeType == OBJECT_OPERATOR)
 			objname = list_make1(objname);
 
 		/* Get an ObjectAddress for the object. */
@@ -356,11 +356,14 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
 			}
 			break;
 		case OBJECT_OPERATOR:
-			if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
-				!type_in_list_does_not_exist_skipping(objargs, &msg, &name))
 			{
-				msg = gettext_noop("operator %s does not exist, skipping");
-				name = NameListToString(objname);
+				FuncWithArgs *fwa = (FuncWithArgs *) linitial(objname);
+				if (!schema_does_not_exist_skipping(fwa->funcname, &msg, &name) &&
+					!type_in_list_does_not_exist_skipping(fwa->funcargs, &msg, &name))
+				{
+					msg = gettext_noop("operator %s does not exist, skipping");
+					name = NameListToString(fwa->funcname);
+				}
 			}
 			break;
 		case OBJECT_LANGUAGE:
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index db45f79..cfda571 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -479,14 +479,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 									" must be between 1 and %d",
 									item->number, maxOpNumber)));
 				if (item->name->funcargs != NIL)
-				{
-					TypeName   *typeName1 = (TypeName *) linitial(item->name->funcargs);
-					TypeName   *typeName2 = (TypeName *) lsecond(item->name->funcargs);
-
-					operOid = LookupOperNameTypeNames(NULL, item->name->funcname,
-													  typeName1, typeName2,
-													  false, -1);
-				}
+					operOid = LookupOperWithArgs(item->name, false);
 				else
 				{
 					/* Default to binary op on input datatype */
@@ -863,14 +856,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 									" must be between 1 and %d",
 									item->number, maxOpNumber)));
 				if (item->name->funcargs != NIL)
-				{
-					TypeName   *typeName1 = (TypeName *) linitial(item->name->funcargs);
-					TypeName   *typeName2 = (TypeName *) lsecond(item->name->funcargs);
-
-					operOid = LookupOperNameTypeNames(NULL, item->name->funcname,
-													  typeName1, typeName2,
-													  false, -1);
-				}
+					operOid = LookupOperWithArgs(item->name, false);
 				else
 				{
 					ereport(ERROR,
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 67d08d8..35b18b0 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -402,10 +402,7 @@ AlterOperator(AlterOperatorStmt *stmt)
 	Oid			joinOid;
 
 	/* Look up the operator */
-	oprId = LookupOperNameTypeNames(NULL, stmt->opername,
-									(TypeName *) linitial(stmt->operargs),
-									(TypeName *) lsecond(stmt->operargs),
-									false, -1);
+	oprId = LookupOperWithArgs(stmt->opername, false);
 	catalog = heap_open(OperatorRelationId, RowExclusiveLock);
 	tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(oprId));
 	if (tup == NULL)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 0da30b1..e794375 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3272,7 +3272,6 @@ _copyAlterOperatorStmt(const AlterOperatorStmt *from)
 	AlterOperatorStmt *newnode = makeNode(AlterOperatorStmt);
 
 	COPY_NODE_FIELD(opername);
-	COPY_NODE_FIELD(operargs);
 	COPY_NODE_FIELD(options);
 
 	return newnode;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index ecff265..6ab3b84 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1380,7 +1380,6 @@ static bool
 _equalAlterOperatorStmt(const AlterOperatorStmt *a, const AlterOperatorStmt *b)
 {
 	COMPARE_NODE_FIELD(opername);
-	COMPARE_NODE_FIELD(operargs);
 	COMPARE_NODE_FIELD(options);
 
 	return true;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 3681208..07086c6 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -338,8 +338,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <accesspriv> privilege
 %type <list>	privileges privilege_list
 %type <privtarget> privilege_target
-%type <funwithargs> function_with_argtypes aggregate_with_argtypes
-%type <list>	function_with_argtypes_list aggregate_with_argtypes_list
+%type <funwithargs> function_with_argtypes aggregate_with_argtypes operator_with_argtypes
+%type <list>	function_with_argtypes_list aggregate_with_argtypes_list operator_with_argtypes_list
 %type <ival>	defacl_privilege_target
 %type <defelt>	DefACLOption
 %type <list>	DefACLOptionList
@@ -4004,14 +4004,13 @@ AlterExtensionContentsStmt:
 					n->objname = list_make1(makeString($7));
 					$$ = (Node *)n;
 				}
-			| ALTER EXTENSION name add_drop OPERATOR any_operator oper_argtypes
+			| ALTER EXTENSION name add_drop OPERATOR operator_with_argtypes
 				{
 					AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
 					n->extname = $3;
 					n->action = $4;
 					n->objtype = OBJECT_OPERATOR;
-					n->objname = $6;
-					n->objargs = $7;
+					n->objname = list_make1($6);
 					$$ = (Node *)n;
 				}
 			| ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING access_method
@@ -5355,17 +5354,14 @@ opclass_item:
 					n->order_family = $4;
 					$$ = (Node *) n;
 				}
-			| OPERATOR Iconst any_operator oper_argtypes opclass_purpose
+			| OPERATOR Iconst operator_with_argtypes opclass_purpose
 			  opt_recheck
 				{
 					CreateOpClassItem *n = makeNode(CreateOpClassItem);
-					FuncWithArgs *fwa = makeNode(FuncWithArgs);
-					fwa->funcname = $3;
-					fwa->funcargs = $4;
 					n->itemtype = OPCLASS_ITEM_OPERATOR;
-					n->name = fwa;
+					n->name = $3;
 					n->number = $2;
-					n->order_family = $5;
+					n->order_family = $4;
 					$$ = (Node *) n;
 				}
 			| FUNCTION Iconst function_with_argtypes
@@ -5789,13 +5785,13 @@ CommentStmt:
 					n->comment = $6;
 					$$ = (Node *) n;
 				}
-			| COMMENT ON OPERATOR any_operator oper_argtypes IS comment_text
+			| COMMENT ON OPERATOR operator_with_argtypes IS comment_text
 				{
 					CommentStmt *n = makeNode(CommentStmt);
 					n->objtype = OBJECT_OPERATOR;
-					n->objname = $4;
-					n->objargs = $5;
-					n->comment = $7;
+					n->objname = list_make1($4);
+					n->objargs = NIL;
+					n->comment = $6;
 					$$ = (Node *) n;
 				}
 			| COMMENT ON CONSTRAINT name ON any_name IS comment_text
@@ -7302,24 +7298,24 @@ RemoveAggrStmt:
 		;
 
 RemoveOperStmt:
-			DROP OPERATOR any_operator oper_argtypes opt_drop_behavior
+			DROP OPERATOR operator_with_argtypes_list opt_drop_behavior
 				{
 					DropStmt *n = makeNode(DropStmt);
 					n->removeType = OBJECT_OPERATOR;
-					n->objects = list_make1($3);
-					n->arguments = list_make1($4);
-					n->behavior = $5;
+					n->objects = $3;
+					n->arguments = NIL;
+					n->behavior = $4;
 					n->missing_ok = false;
 					n->concurrent = false;
 					$$ = (Node *)n;
 				}
-			| DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior
+			| DROP OPERATOR IF_P EXISTS operator_with_argtypes_list opt_drop_behavior
 				{
 					DropStmt *n = makeNode(DropStmt);
 					n->removeType = OBJECT_OPERATOR;
-					n->objects = list_make1($5);
-					n->arguments = list_make1($6);
-					n->behavior = $7;
+					n->objects = $5;
+					n->arguments = NIL;
+					n->behavior = $6;
 					n->missing_ok = true;
 					n->concurrent = false;
 					$$ = (Node *)n;
@@ -7350,6 +7346,22 @@ any_operator:
 					{ $$ = lcons(makeString($1), $3); }
 		;
 
+operator_with_argtypes_list:
+			operator_with_argtypes					{ $$ = list_make1($1); }
+			| operator_with_argtypes_list ',' operator_with_argtypes
+													{ $$ = lappend($1, $3); }
+		;
+
+operator_with_argtypes:
+			any_operator oper_argtypes
+				{
+					FuncWithArgs *n = makeNode(FuncWithArgs);
+					n->funcname = $1;
+					n->funcargs = $2;
+					$$ = n;
+				}
+		;
+
 /*****************************************************************************
  *
  *		DO <anonymous code block> [ LANGUAGE language ]
@@ -8177,13 +8189,12 @@ AlterObjectSchemaStmt:
 					n->missing_ok = false;
 					$$ = (Node *)n;
 				}
-			| ALTER OPERATOR any_operator oper_argtypes SET SCHEMA name
+			| ALTER OPERATOR operator_with_argtypes SET SCHEMA name
 				{
 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
 					n->objectType = OBJECT_OPERATOR;
-					n->object = $3;
-					n->objarg = $4;
-					n->newschema = $7;
+					n->object = list_make1($3);
+					n->newschema = $6;
 					n->missing_ok = false;
 					$$ = (Node *)n;
 				}
@@ -8349,12 +8360,11 @@ AlterObjectSchemaStmt:
  *****************************************************************************/
 
 AlterOperatorStmt:
-			ALTER OPERATOR any_operator oper_argtypes SET '(' operator_def_list ')'
+			ALTER OPERATOR operator_with_argtypes SET '(' operator_def_list ')'
 				{
 					AlterOperatorStmt *n = makeNode(AlterOperatorStmt);
 					n->opername = $3;
-					n->operargs = $4;
-					n->options = $7;
+					n->options = $6;
 					$$ = (Node *)n;
 				}
 		;
@@ -8439,13 +8449,12 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
 					n->newowner = $7;
 					$$ = (Node *)n;
 				}
-			| ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleSpec
+			| ALTER OPERATOR operator_with_argtypes OWNER TO RoleSpec
 				{
 					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
 					n->objectType = OBJECT_OPERATOR;
-					n->object = $3;
-					n->objarg = $4;
-					n->newowner = $7;
+					n->object = list_make1($3);
+					n->newowner = $6;
 					$$ = (Node *)n;
 				}
 			| ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleSpec
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index aecda6d..006d978 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -132,32 +132,35 @@ LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
 }
 
 /*
- * LookupOperNameTypeNames
+ * LookupOperWithArgs
  *		Like LookupOperName, but the argument types are specified by
- *		TypeName nodes.
- *
- * Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op.
+ *		a FuncWithArg node.
  */
 Oid
-LookupOperNameTypeNames(ParseState *pstate, List *opername,
-						TypeName *oprleft, TypeName *oprright,
-						bool noError, int location)
+LookupOperWithArgs(FuncWithArgs *oper,
+						bool noError)
 {
+	TypeName   *oprleft,
+			   *oprright;
 	Oid			leftoid,
 				rightoid;
 
+	Assert(list_length(oper->funcargs) == 2);
+	oprleft = linitial(oper->funcargs);
+	oprright = lsecond(oper->funcargs);
+
 	if (oprleft == NULL)
 		leftoid = InvalidOid;
 	else
-		leftoid = LookupTypeNameOid(pstate, oprleft, noError);
+		leftoid = LookupTypeNameOid(NULL, oprleft, noError);
 
 	if (oprright == NULL)
 		rightoid = InvalidOid;
 	else
-		rightoid = LookupTypeNameOid(pstate, oprright, noError);
+		rightoid = LookupTypeNameOid(NULL, oprright, noError);
 
-	return LookupOperName(pstate, opername, leftoid, rightoid,
-						  noError, location);
+	return LookupOperName(NULL, oper->funcname, leftoid, rightoid,
+						  noError, -1);
 }
 
 /*
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 564ed50..8a1f530 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2587,8 +2587,7 @@ typedef struct AlterOwnerStmt
 typedef struct AlterOperatorStmt
 {
 	NodeTag		type;
-	List	   *opername;		/* operator name */
-	List	   *operargs;		/* operator's argument TypeNames */
+	FuncWithArgs *opername;		/* operator name and argument types */
 	List	   *options;		/* List of DefElem nodes */
 } AlterOperatorStmt;
 
diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h
index 03bb5b9..51c1247 100644
--- a/src/include/parser/parse_oper.h
+++ b/src/include/parser/parse_oper.h
@@ -15,6 +15,7 @@
 #define PARSE_OPER_H
 
 #include "access/htup.h"
+#include "nodes/parsenodes.h"
 #include "parser/parse_node.h"
 
 
@@ -24,9 +25,7 @@ typedef HeapTuple Operator;
 extern Oid LookupOperName(ParseState *pstate, List *opername,
 			   Oid oprleft, Oid oprright,
 			   bool noError, int location);
-extern Oid LookupOperNameTypeNames(ParseState *pstate, List *opername,
-						TypeName *oprleft, TypeName *oprright,
-						bool noError, int location);
+extern Oid LookupOperWithArgs(FuncWithArgs *oper, bool noError);
 
 /* Routines to find operators matching a name and given input types */
 /* NB: the selected operator may require coercion of the input types! */
-- 
2.10.2

