drop_func_if_not_exists_fix_v5.patch

application/octet-stream

Filename: drop_func_if_not_exists_fix_v5.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #15572: Misleading message reported by "Drop function operation" on DB with functions having same name

Patch

Format: unified
Series: patch v5
File+
src/backend/catalog/aclchk.c 6 3
src/backend/catalog/objectaddress.c 3 1
src/backend/commands/amcmds.c 2 1
src/backend/commands/conversioncmds.c 1 1
src/backend/commands/event_trigger.c 1 1
src/backend/commands/foreigncmds.c 4 2
src/backend/commands/functioncmds.c 7 4
src/backend/commands/opclasscmds.c 4 2
src/backend/commands/operatorcmds.c 7 5
src/backend/commands/proclang.c 12 6
src/backend/commands/trigger.c 2 1
src/backend/commands/tsearchcmds.c 2 2
src/backend/commands/typecmds.c 14 14
src/backend/parser/parse_clause.c 1 1
src/backend/parser/parse_func.c 27 12
src/include/parser/parse_func.h 9 2
src/pl/tcl/pltcl.c 1 1
src/test/regress/expected/drop_if_exists.out 10 0
src/test/regress/sql/drop_if_exists.sql 10 0
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 11ddce2a8b..f92f2f0a25 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -681,7 +681,8 @@ objectNamesToOids(ObjectType objtype, List *objnames)
 				ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
 				Oid			funcid;
 
-				funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
+				funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func,
+											FUNCLOOKUP_NORMAL);
 				objects = lappend_oid(objects, funcid);
 			}
 			break;
@@ -725,7 +726,8 @@ objectNamesToOids(ObjectType objtype, List *objnames)
 				ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
 				Oid			procid;
 
-				procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
+				procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func,
+											FUNCLOOKUP_NORMAL);
 				objects = lappend_oid(objects, procid);
 			}
 			break;
@@ -735,7 +737,8 @@ objectNamesToOids(ObjectType objtype, List *objnames)
 				ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
 				Oid			routid;
 
-				routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
+				routid = LookupFuncWithArgs(OBJECT_ROUTINE, func,
+											FUNCLOOKUP_NORMAL);
 				objects = lappend_oid(objects, routid);
 			}
 			break;
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index ab3ec7e356..2f6fd892bf 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -926,7 +926,9 @@ get_object_address(ObjectType objtype, Node *object,
 			case OBJECT_PROCEDURE:
 			case OBJECT_ROUTINE:
 				address.classId = ProcedureRelationId;
-				address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object), missing_ok);
+				address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object),
+													  missing_ok ? FUNCLOOKUP_ERRIFAMBIGUOUS :
+													  FUNCLOOKUP_NORMAL);
 				address.objectSubId = 0;
 				break;
 			case OBJECT_OPERATOR:
diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c
index c84507b5d0..db27616f32 100644
--- a/src/backend/commands/amcmds.c
+++ b/src/backend/commands/amcmds.c
@@ -254,7 +254,8 @@ lookup_index_am_handler_func(List *handler_name, char amtype)
 				 errmsg("handler function is not specified")));
 
 	/* handlers have one argument of type internal */
-	handlerOid = LookupFuncName(handler_name, 1, funcargtypes, false);
+	handlerOid = LookupFuncName(handler_name, 1, funcargtypes,
+								FUNCLOOKUP_NORMAL);
 
 	/* check that handler has the correct return type */
 	switch (amtype)
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 5afe86712f..1329c58d27 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -77,7 +77,7 @@ CreateConversionCommand(CreateConversionStmt *stmt)
 	 * a qualified name.
 	 */
 	funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid),
-							 funcargs, false);
+							 funcargs, FUNCLOOKUP_NORMAL);
 
 	/* Check it returns VOID, else it's probably the wrong function */
 	if (get_func_rettype(funcoid) != VOIDOID)
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index adb77d8f69..8e922e6c2a 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -238,7 +238,7 @@ CreateEventTrigger(CreateEventTrigStmt *stmt)
 						stmt->trigname)));
 
 	/* Find and validate the trigger function. */
-	funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
+	funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, FUNCLOOKUP_NORMAL);
 	funcrettype = get_func_rettype(funcoid);
 	if (funcrettype != EVTTRIGGEROID)
 		ereport(ERROR,
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index 413ce3fcb6..9cb4dadfc4 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -484,7 +484,8 @@ lookup_fdw_handler_func(DefElem *handler)
 		return InvalidOid;
 
 	/* handlers have no arguments */
-	handlerOid = LookupFuncName((List *) handler->arg, 0, funcargtypes, false);
+	handlerOid = LookupFuncName((List *) handler->arg, 0, funcargtypes,
+								FUNCLOOKUP_NORMAL);
 
 	/* check that handler has correct return type */
 	if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
@@ -511,7 +512,8 @@ lookup_fdw_validator_func(DefElem *validator)
 	funcargtypes[0] = TEXTARRAYOID;
 	funcargtypes[1] = OIDOID;
 
-	return LookupFuncName((List *) validator->arg, 2, funcargtypes, false);
+	return LookupFuncName((List *) validator->arg, 2, funcargtypes,
+						  FUNCLOOKUP_NORMAL);
 	/* validator's return value is ignored, so we don't check the type */
 }
 
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 4f62e48d98..c3a350d6ed 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -658,7 +658,7 @@ interpret_func_support(DefElem *defel)
 	 */
 	argList[0] = INTERNALOID;
 
-	procOid = LookupFuncName(procName, 1, argList, true);
+	procOid = LookupFuncName(procName, 1, argList, FUNCLOOKUP_NOERROR);
 	if (!OidIsValid(procOid))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
@@ -1251,7 +1251,8 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
 
 	rel = table_open(ProcedureRelationId, RowExclusiveLock);
 
-	funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
+	funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func,
+								 FUNCLOOKUP_NORMAL);
 
 	ObjectAddressSet(address, ProcedureRelationId, funcOid);
 
@@ -1567,7 +1568,8 @@ CreateCast(CreateCastStmt *stmt)
 	{
 		Form_pg_proc procstruct;
 
-		funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
+		funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func,
+									FUNCLOOKUP_NORMAL);
 
 		tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 		if (!HeapTupleIsValid(tuple))
@@ -1942,7 +1944,8 @@ CreateTransform(CreateTransformStmt *stmt)
 	 */
 	if (stmt->fromsql)
 	{
-		fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
+		fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql,
+										   FUNCLOOKUP_NORMAL);
 
 		if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 5d73848a8b..34312e5e72 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -529,7 +529,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
 							 errmsg("invalid function number %d,"
 									" must be between 1 and %d",
 									item->number, maxProcNumber)));
-				funcOid = LookupFuncWithArgs(OBJECT_FUNCTION, item->name, false);
+				funcOid = LookupFuncWithArgs(OBJECT_FUNCTION, item->name,
+											 FUNCLOOKUP_NORMAL);
 #ifdef NOT_USED
 				/* XXX this is unnecessary given the superuser check above */
 				/* Caller must own function */
@@ -908,7 +909,8 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 							 errmsg("invalid function number %d,"
 									" must be between 1 and %d",
 									item->number, maxProcNumber)));
-				funcOid = LookupFuncWithArgs(OBJECT_FUNCTION, item->name, false);
+				funcOid = LookupFuncWithArgs(OBJECT_FUNCTION, item->name,
+											 FUNCLOOKUP_NORMAL);
 #ifdef NOT_USED
 				/* XXX this is unnecessary given the superuser check above */
 				/* Caller must own function */
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 7b98e4b910..6c1bc5208e 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -208,7 +208,8 @@ DefineOperator(List *names, List *parameters)
 		typeId[1] = typeId2;
 		nargs = 2;
 	}
-	functionOid = LookupFuncName(functionName, nargs, typeId, false);
+	functionOid = LookupFuncName(functionName, nargs, typeId,
+								 FUNCLOOKUP_NORMAL);
 
 	/*
 	 * We require EXECUTE rights for the function.  This isn't strictly
@@ -271,7 +272,8 @@ ValidateRestrictionEstimator(List *restrictionName)
 	typeId[2] = INTERNALOID;	/* args list */
 	typeId[3] = INT4OID;		/* varRelid */
 
-	restrictionOid = LookupFuncName(restrictionName, 4, typeId, false);
+	restrictionOid = LookupFuncName(restrictionName, 4, typeId,
+									FUNCLOOKUP_NORMAL);
 
 	/* estimators must return float8 */
 	if (get_func_rettype(restrictionOid) != FLOAT8OID)
@@ -312,12 +314,12 @@ ValidateJoinEstimator(List *joinName)
 	 * arguments, but we still allow the old 4-argument form. Try the
 	 * preferred form first.
 	 */
-	joinOid = LookupFuncName(joinName, 5, typeId, true);
+	joinOid = LookupFuncName(joinName, 5, typeId, FUNCLOOKUP_NOERROR);
 	if (!OidIsValid(joinOid))
-		joinOid = LookupFuncName(joinName, 4, typeId, true);
+		joinOid = LookupFuncName(joinName, 4, typeId, FUNCLOOKUP_NOERROR);
 	/* If not found, reference the 5-argument signature in error msg */
 	if (!OidIsValid(joinOid))
-		joinOid = LookupFuncName(joinName, 5, typeId, false);
+		joinOid = LookupFuncName(joinName, 5, typeId, FUNCLOOKUP_NORMAL);
 
 	/* estimators must return float8 */
 	if (get_func_rettype(joinOid) != FLOAT8OID)
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 59c4e8dfd0..e94ca419be 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -106,7 +106,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		 * return type.
 		 */
 		funcname = SystemFuncName(pltemplate->tmplhandler);
-		handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
+		handlerOid = LookupFuncName(funcname, 0, funcargtypes,
+									FUNCLOOKUP_NOERROR);
 		if (OidIsValid(handlerOid))
 		{
 			funcrettype = get_func_rettype(handlerOid);
@@ -155,7 +156,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		{
 			funcname = SystemFuncName(pltemplate->tmplinline);
 			funcargtypes[0] = INTERNALOID;
-			inlineOid = LookupFuncName(funcname, 1, funcargtypes, true);
+			inlineOid = LookupFuncName(funcname, 1, funcargtypes,
+									   FUNCLOOKUP_NOERROR);
 			if (!OidIsValid(inlineOid))
 			{
 				tmpAddr = ProcedureCreate(pltemplate->tmplinline,
@@ -198,7 +200,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		{
 			funcname = SystemFuncName(pltemplate->tmplvalidator);
 			funcargtypes[0] = OIDOID;
-			valOid = LookupFuncName(funcname, 1, funcargtypes, true);
+			valOid = LookupFuncName(funcname, 1, funcargtypes,
+									FUNCLOOKUP_NOERROR);
 			if (!OidIsValid(valOid))
 			{
 				tmpAddr = ProcedureCreate(pltemplate->tmplvalidator,
@@ -264,7 +267,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		 * Lookup the PL handler function and check that it is of the expected
 		 * return type
 		 */
-		handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
+		handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes,
+									FUNCLOOKUP_NORMAL);
 		funcrettype = get_func_rettype(handlerOid);
 		if (funcrettype != LANGUAGE_HANDLEROID)
 		{
@@ -293,7 +297,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		if (stmt->plinline)
 		{
 			funcargtypes[0] = INTERNALOID;
-			inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
+			inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes,
+									   FUNCLOOKUP_NORMAL);
 			/* return value is ignored, so we don't check the type */
 		}
 		else
@@ -303,7 +308,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		if (stmt->plvalidator)
 		{
 			funcargtypes[0] = OIDOID;
-			valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
+			valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes,
+									FUNCLOOKUP_NORMAL);
 			/* return value is ignored, so we don't check the type */
 		}
 		else
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 0b245a613e..68fb839524 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -667,7 +667,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 	 * Find and validate the trigger function.
 	 */
 	if (!OidIsValid(funcoid))
-		funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
+		funcoid = LookupFuncName(stmt->funcname, 0, fargtypes,
+								 FUNCLOOKUP_NORMAL);
 	if (!isInternal)
 	{
 		aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 8e5eec22b5..30d3635598 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -108,7 +108,7 @@ get_ts_parser_func(DefElem *defel, int attnum)
 			nargs = 0;			/* keep compiler quiet */
 	}
 
-	procOid = LookupFuncName(funcName, nargs, typeId, false);
+	procOid = LookupFuncName(funcName, nargs, typeId, FUNCLOOKUP_NORMAL);
 	if (get_func_rettype(procOid) != retTypeId)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -679,7 +679,7 @@ get_ts_template_func(DefElem *defel, int attnum)
 			nargs = 0;			/* keep compiler quiet */
 	}
 
-	procOid = LookupFuncName(funcName, nargs, typeId, false);
+	procOid = LookupFuncName(funcName, nargs, typeId, FUNCLOOKUP_NORMAL);
 	if (get_func_rettype(procOid) != retTypeId)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 448926db12..fe7a5c1017 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1700,28 +1700,28 @@ findTypeInputFunction(List *procname, Oid typeOid)
 	 */
 	argList[0] = CSTRINGOID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (OidIsValid(procOid))
 		return procOid;
 
 	argList[1] = OIDOID;
 	argList[2] = INT4OID;
 
-	procOid = LookupFuncName(procname, 3, argList, true);
+	procOid = LookupFuncName(procname, 3, argList, FUNCLOOKUP_NOERROR);
 	if (OidIsValid(procOid))
 		return procOid;
 
 	/* No luck, try it with OPAQUE */
 	argList[0] = OPAQUEOID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 
 	if (!OidIsValid(procOid))
 	{
 		argList[1] = OIDOID;
 		argList[2] = INT4OID;
 
-		procOid = LookupFuncName(procname, 3, argList, true);
+		procOid = LookupFuncName(procname, 3, argList, FUNCLOOKUP_NOERROR);
 	}
 
 	if (OidIsValid(procOid))
@@ -1766,14 +1766,14 @@ findTypeOutputFunction(List *procname, Oid typeOid)
 	 */
 	argList[0] = typeOid;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (OidIsValid(procOid))
 		return procOid;
 
 	/* No luck, try it with OPAQUE */
 	argList[0] = OPAQUEOID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 
 	if (OidIsValid(procOid))
 	{
@@ -1815,14 +1815,14 @@ findTypeReceiveFunction(List *procname, Oid typeOid)
 	 */
 	argList[0] = INTERNALOID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (OidIsValid(procOid))
 		return procOid;
 
 	argList[1] = OIDOID;
 	argList[2] = INT4OID;
 
-	procOid = LookupFuncName(procname, 3, argList, true);
+	procOid = LookupFuncName(procname, 3, argList, FUNCLOOKUP_NOERROR);
 	if (OidIsValid(procOid))
 		return procOid;
 
@@ -1845,7 +1845,7 @@ findTypeSendFunction(List *procname, Oid typeOid)
 	 */
 	argList[0] = typeOid;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (OidIsValid(procOid))
 		return procOid;
 
@@ -1868,7 +1868,7 @@ findTypeTypmodinFunction(List *procname)
 	 */
 	argList[0] = CSTRINGARRAYOID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (!OidIsValid(procOid))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
@@ -1895,7 +1895,7 @@ findTypeTypmodoutFunction(List *procname)
 	 */
 	argList[0] = INT4OID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (!OidIsValid(procOid))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
@@ -1922,7 +1922,7 @@ findTypeAnalyzeFunction(List *procname, Oid typeOid)
 	 */
 	argList[0] = INTERNALOID;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 	if (!OidIsValid(procOid))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
@@ -1998,7 +1998,7 @@ findRangeCanonicalFunction(List *procname, Oid typeOid)
 	 */
 	argList[0] = typeOid;
 
-	procOid = LookupFuncName(procname, 1, argList, true);
+	procOid = LookupFuncName(procname, 1, argList, FUNCLOOKUP_NOERROR);
 
 	if (!OidIsValid(procOid))
 		ereport(ERROR,
@@ -2040,7 +2040,7 @@ findRangeSubtypeDiffFunction(List *procname, Oid subtype)
 	argList[0] = subtype;
 	argList[1] = subtype;
 
-	procOid = LookupFuncName(procname, 2, argList, true);
+	procOid = LookupFuncName(procname, 2, argList, FUNCLOOKUP_NOERROR);
 
 	if (!OidIsValid(procOid))
 		ereport(ERROR,
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index c6ce1011e2..35fc73b493 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -933,7 +933,7 @@ transformRangeTableSample(ParseState *pstate, RangeTableSample *rts)
 	 */
 	funcargtypes[0] = INTERNALOID;
 
-	handlerOid = LookupFuncName(rts->method, 1, funcargtypes, true);
+	handlerOid = LookupFuncName(rts->method, 1, funcargtypes, FUNCLOOKUP_NOERROR);
 
 	/* we want error to complain about no-such-method, not no-such-function */
 	if (!OidIsValid(handlerOid))
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 5222231b51..4192ae9b2d 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -2031,18 +2031,25 @@ func_signature_string(List *funcname, int nargs,
  * If the function name is not schema-qualified, it is sought in the current
  * namespace search path.
  *
- * If the function is not found, we return InvalidOid if noError is true,
- * else raise an error.
+ * If the function is not found the behavior depends on the value of
+ * 'checktype'.  When it's set to FUNCLOOKUP_NORMAL, we report errors for each
+ * of the possible error situations.  When set to FUNCLOOKUP_ERRIFAMBIGUOUS,
+ * the only error we raise is for an ambiguous function definition, otherwise
+ * if set to FUNCLOOKUP_NOERROR we don't raise any errors.  In each of the
+ * cases we skip reporting an error, we return InvalidOid to indicate to the
+ * caller that the lookup has failed.
  */
 Oid
-LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
+LookupFuncName(List *funcname, int nargs, const Oid *argtypes,
+			   FuncLookupCheckType checktype)
 {
 	FuncCandidateList clist;
 
 	/* Passing NULL for argtypes is no longer allowed */
 	Assert(argtypes);
 
-	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError);
+	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false,
+								  (checktype != FUNCLOOKUP_NORMAL));
 
 	/*
 	 * If no arguments were specified, the name must yield a unique candidate.
@@ -2053,7 +2060,11 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
 		{
 			if (clist->next)
 			{
-				if (!noError)
+				/*
+				 * Raise this error on FUNCLOOKUP_NORMAL and
+				 * FUNCLOOKUP_ERRIFAMBIGUOUS
+				 */
+				if (checktype != FUNCLOOKUP_NOERROR)
 					ereport(ERROR,
 							(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
 							 errmsg("function name \"%s\" is not unique",
@@ -2065,7 +2076,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
 		}
 		else
 		{
-			if (!noError)
+			if (checktype == FUNCLOOKUP_NORMAL)
 				ereport(ERROR,
 						(errcode(ERRCODE_UNDEFINED_FUNCTION),
 						 errmsg("could not find a function named \"%s\"",
@@ -2080,7 +2091,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
 		clist = clist->next;
 	}
 
-	if (!noError)
+	if (checktype == FUNCLOOKUP_NORMAL)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
 				 errmsg("function %s does not exist",
@@ -2102,10 +2113,12 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
  * function.
  */
 Oid
-LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
+LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func,
+				   FuncLookupCheckType checktype)
 {
 	Oid			argoids[FUNC_MAX_ARGS];
 	int			argcount;
+	bool		noError = (checktype != FUNCLOOKUP_NORMAL);
 	int			i;
 	ListCell   *args_item;
 	Oid			oid;
@@ -2134,12 +2147,14 @@ LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
 	}
 
 	/*
-	 * When looking for a function or routine, we pass noError through to
-	 * LookupFuncName and let it make any error messages.  Otherwise, we make
+	 * When looking for a function or routine, we pass checktype through to
+	 * LookupFuncNameand let it make any error messages.  Otherwise, we make
 	 * our own errors for the aggregate and procedure cases.
 	 */
-	oid = LookupFuncName(func->objname, func->args_unspecified ? -1 : argcount, argoids,
-						 (objtype == OBJECT_FUNCTION || objtype == OBJECT_ROUTINE) ? noError : true);
+	oid = LookupFuncName(func->objname,
+						 func->args_unspecified ? -1 : argcount,
+						 argoids,
+						 (objtype == OBJECT_FUNCTION || objtype == OBJECT_ROUTINE) ? checktype : FUNCLOOKUP_NOERROR);
 
 	if (objtype == OBJECT_FUNCTION)
 	{
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index ff1477e64f..d279183f17 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -30,6 +30,13 @@ typedef enum
 	FUNCDETAIL_COERCION			/* it's a type coercion request */
 } FuncDetailCode;
 
+/* Error checking types for LookupFuncName and LookupFuncWithArgs */
+typedef enum
+{
+	FUNCLOOKUP_NORMAL,			/* Full error checking */
+	FUNCLOOKUP_NOERROR,			/* Don't raise error for lookup failure */
+	FUNCLOOKUP_ERRIFAMBIGUOUS	/* Only raise ambiguous function errors */
+} FuncLookupCheckType;
 
 extern Node *ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
 				  Node *last_srf, FuncCall *fn, bool proc_call,
@@ -63,9 +70,9 @@ extern const char *func_signature_string(List *funcname, int nargs,
 					  List *argnames, const Oid *argtypes);
 
 extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes,
-			   bool noError);
+			   FuncLookupCheckType checktype);
 extern Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func,
-				   bool noError);
+				   FuncLookupCheckType checktype);
 
 extern void check_srf_call_placement(ParseState *pstate, Node *last_srf,
 						 int location);
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index bfbf62305c..f075d2589a 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -616,7 +616,7 @@ call_pltcl_start_proc(Oid prolang, bool pltrusted)
 
 	/* Parse possibly-qualified identifier and look up the function */
 	namelist = stringToQualifiedNameList(start_proc);
-	procOid = LookupFuncName(namelist, 0, fargtypes, false);
+	procOid = LookupFuncName(namelist, 0, fargtypes, FUNCLOOKUP_NORMAL);
 
 	/* Current user must have permission to call function */
 	aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
diff --git a/src/test/regress/expected/drop_if_exists.out b/src/test/regress/expected/drop_if_exists.out
index b80c5ed2d8..dd4e6c0f6d 100644
--- a/src/test/regress/expected/drop_if_exists.out
+++ b/src/test/regress/expected/drop_if_exists.out
@@ -138,6 +138,16 @@ DROP FUNCTION test_function_exists(int, text, int[]);
 ERROR:  function test_function_exists(integer, text, integer[]) does not exist
 DROP FUNCTION IF EXISTS test_function_exists(int, text, int[]);
 NOTICE:  function test_function_exists(pg_catalog.int4,text,pg_catalog.int4[]) does not exist, skipping
+-- Ensure we still receive an ambiguous function error when there are
+-- multiple matching functions.
+CREATE FUNCTION test_ambiguous_funcname(int) returns int as $$ select $1; $$ language sql;
+CREATE FUNCTION test_ambiguous_funcname(text) returns text as $$ select $1; $$ language sql;
+DROP FUNCTION IF EXISTS test_ambiguous_funcname;
+ERROR:  function name "test_ambiguous_funcname" is not unique
+HINT:  Specify the argument list to select the function unambiguously.
+-- cleanup
+DROP FUNCTION test_ambiguous_funcname(int);
+DROP FUNCTION test_ambiguous_funcname(text);
 -- aggregate
 DROP AGGREGATE test_aggregate_exists(*);
 ERROR:  aggregate test_aggregate_exists(*) does not exist
diff --git a/src/test/regress/sql/drop_if_exists.sql b/src/test/regress/sql/drop_if_exists.sql
index c1d30bc4a5..ad4ef76460 100644
--- a/src/test/regress/sql/drop_if_exists.sql
+++ b/src/test/regress/sql/drop_if_exists.sql
@@ -153,6 +153,16 @@ DROP FUNCTION IF EXISTS test_function_exists();
 DROP FUNCTION test_function_exists(int, text, int[]);
 DROP FUNCTION IF EXISTS test_function_exists(int, text, int[]);
 
+-- Ensure we still receive an ambiguous function error when there are
+-- multiple matching functions.
+CREATE FUNCTION test_ambiguous_funcname(int) returns int as $$ select $1; $$ language sql;
+CREATE FUNCTION test_ambiguous_funcname(text) returns text as $$ select $1; $$ language sql;
+DROP FUNCTION IF EXISTS test_ambiguous_funcname;
+
+-- cleanup
+DROP FUNCTION test_ambiguous_funcname(int);
+DROP FUNCTION test_ambiguous_funcname(text);
+
 -- aggregate
 DROP AGGREGATE test_aggregate_exists(*);
 DROP AGGREGATE IF EXISTS test_aggregate_exists(*);