summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/nodes/copyfuncs.c1
-rw-r--r--src/backend/nodes/equalfuncs.c1
-rw-r--r--src/backend/parser/gram.y27
-rw-r--r--src/backend/parser/parse_func.c37
4 files changed, 63 insertions, 3 deletions
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index bfc2ac17165..25fd051d6ef 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3067,6 +3067,7 @@ _copyObjectWithArgs(const ObjectWithArgs *from)
COPY_NODE_FIELD(objname);
COPY_NODE_FIELD(objargs);
+ COPY_SCALAR_FIELD(args_unspecified);
return newnode;
}
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 54e9c983a0f..67529e3f861 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1119,6 +1119,7 @@ _equalObjectWithArgs(const ObjectWithArgs *a, const ObjectWithArgs *b)
{
COMPARE_NODE_FIELD(objname);
COMPARE_NODE_FIELD(objargs);
+ COMPARE_SCALAR_FIELD(args_unspecified);
return true;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e7acc2d9a23..6316688a883 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7202,6 +7202,33 @@ function_with_argtypes:
n->objargs = extractArgTypes($2);
$$ = n;
}
+ /*
+ * Because of reduce/reduce conflicts, we can't use func_name
+ * below, but we can write it out the long way, which actually
+ * allows more cases.
+ */
+ | type_func_name_keyword
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = list_make1(makeString(pstrdup($1)));
+ n->args_unspecified = true;
+ $$ = n;
+ }
+ | ColId
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = list_make1(makeString($1));
+ n->args_unspecified = true;
+ $$ = n;
+ }
+ | ColId indirection
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = check_func_name(lcons(makeString($1), $2),
+ yyscanner);
+ n->args_unspecified = true;
+ $$ = n;
+ }
;
/*
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index dd9749f2056..55853c20bb4 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -1895,8 +1895,10 @@ func_signature_string(List *funcname, int nargs,
/*
* LookupFuncName
- * Given a possibly-qualified function name and a set of argument types,
- * look up the function.
+ *
+ * Given a possibly-qualified function name and optionally a set of argument
+ * types, look up the function. Pass nargs == -1 to indicate that no argument
+ * types are specified.
*
* If the function name is not schema-qualified, it is sought in the current
* namespace search path.
@@ -1914,6 +1916,35 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError);
+ /*
+ * If no arguments were specified, the name must yield a unique candidate.
+ */
+ if (nargs == -1)
+ {
+ if (clist)
+ {
+ if (clist->next)
+ {
+ if (!noError)
+ ereport(ERROR,
+ (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
+ errmsg("function name \"%s\" is not unique",
+ NameListToString(funcname)),
+ errhint("Specify the argument list to select the function unambiguously.")));
+ }
+ else
+ return clist->oid;
+ }
+ else
+ {
+ if (!noError)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not find a function named \"%s\"",
+ NameListToString(funcname))));
+ }
+ }
+
while (clist)
{
if (memcmp(argtypes, clist->args, nargs * sizeof(Oid)) == 0)
@@ -1962,7 +1993,7 @@ LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
args_item = lnext(args_item);
}
- return LookupFuncName(func->objname, argcount, argoids, noError);
+ return LookupFuncName(func->objname, func->args_unspecified ? -1 : argcount, argoids, noError);
}
/*