diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 1 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 1 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 27 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 37 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 3 | ||||
-rw-r--r-- | src/test/regress/expected/create_function_3.out | 11 | ||||
-rw-r--r-- | src/test/regress/sql/create_function_3.sql | 8 |
7 files changed, 84 insertions, 4 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); } /* diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index a44d2178e1c..d576523f6a8 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1811,6 +1811,9 @@ typedef struct ObjectWithArgs NodeTag type; List *objname; /* qualified name of function/operator */ List *objargs; /* list of Typename nodes */ + bool args_unspecified; /* argument list was omitted, so name must + * be unique (note that objargs == NIL means + * zero args) */ } ObjectWithArgs; /* diff --git a/src/test/regress/expected/create_function_3.out b/src/test/regress/expected/create_function_3.out index cc4e98a1d4b..b5e19485e56 100644 --- a/src/test/regress/expected/create_function_3.out +++ b/src/test/regress/expected/create_function_3.out @@ -218,13 +218,21 @@ SELECT routine_name, ordinal_position, parameter_name, parameter_default (7 rows) DROP FUNCTION functest_IS_1(int, int, text), functest_IS_2(int), functest_IS_3(int); +-- overload +CREATE FUNCTION functest_B_2(bigint) RETURNS bool LANGUAGE 'sql' + IMMUTABLE AS 'SELECT $1 > 0'; +DROP FUNCTION functest_b_1; +DROP FUNCTION functest_b_1; -- error, not found +ERROR: could not find a function named "functest_b_1" +DROP FUNCTION functest_b_2; -- error, ambiguous +ERROR: function name "functest_b_2" is not unique +HINT: Specify the argument list to select the function unambiguously. -- Cleanups DROP SCHEMA temp_func_test CASCADE; NOTICE: drop cascades to 16 other objects DETAIL: drop cascades to function functest_a_1(text,date) drop cascades to function functest_a_2(text[]) drop cascades to function functest_a_3() -drop cascades to function functest_b_1(integer) drop cascades to function functest_b_2(integer) drop cascades to function functest_b_3(integer) drop cascades to function functest_b_4(integer) @@ -237,5 +245,6 @@ drop cascades to function functext_f_1(integer) drop cascades to function functext_f_2(integer) drop cascades to function functext_f_3(integer) drop cascades to function functext_f_4(integer) +drop cascades to function functest_b_2(bigint) DROP USER regress_unpriv_user; RESET search_path; diff --git a/src/test/regress/sql/create_function_3.sql b/src/test/regress/sql/create_function_3.sql index 66a463b0895..0a0e407aaba 100644 --- a/src/test/regress/sql/create_function_3.sql +++ b/src/test/regress/sql/create_function_3.sql @@ -158,6 +158,14 @@ SELECT routine_name, ordinal_position, parameter_name, parameter_default DROP FUNCTION functest_IS_1(int, int, text), functest_IS_2(int), functest_IS_3(int); +-- overload +CREATE FUNCTION functest_B_2(bigint) RETURNS bool LANGUAGE 'sql' + IMMUTABLE AS 'SELECT $1 > 0'; + +DROP FUNCTION functest_b_1; +DROP FUNCTION functest_b_1; -- error, not found +DROP FUNCTION functest_b_2; -- error, ambiguous + -- Cleanups DROP SCHEMA temp_func_test CASCADE; |