diff options
-rw-r--r-- | doc/src/sgml/ref/alter_extension.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_function.sgml | 13 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_opfamily.sgml | 7 | ||||
-rw-r--r-- | doc/src/sgml/ref/comment.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_cast.sgml | 6 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_transform.sgml | 12 | ||||
-rw-r--r-- | doc/src/sgml/ref/drop_function.sgml | 35 | ||||
-rw-r--r-- | doc/src/sgml/ref/grant.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/ref/revoke.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/ref/security_label.sgml | 2 | ||||
-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 |
17 files changed, 143 insertions, 28 deletions
diff --git a/doc/src/sgml/ref/alter_extension.sgml b/doc/src/sgml/ref/alter_extension.sgml index de6d6dca16b..a7c0927d1c9 100644 --- a/doc/src/sgml/ref/alter_extension.sgml +++ b/doc/src/sgml/ref/alter_extension.sgml @@ -39,7 +39,7 @@ ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> DROP <replacea EVENT TRIGGER <replaceable class="PARAMETER">object_name</replaceable> | FOREIGN DATA WRAPPER <replaceable class="PARAMETER">object_name</replaceable> | FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> | - FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) | + FUNCTION <replaceable class="PARAMETER">function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] | MATERIALIZED VIEW <replaceable class="PARAMETER">object_name</replaceable> | OPERATOR <replaceable class="PARAMETER">operator_name</replaceable> (<replaceable class="PARAMETER">left_type</replaceable>, <replaceable class="PARAMETER">right_type</replaceable>) | OPERATOR CLASS <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> | diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml index 0388d06b959..168eeb7c526 100644 --- a/doc/src/sgml/ref/alter_function.sgml +++ b/doc/src/sgml/ref/alter_function.sgml @@ -21,15 +21,15 @@ PostgreSQL documentation <refsynopsisdiv> <synopsis> -ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) +ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] <replaceable class="PARAMETER">action</replaceable> [ ... ] [ RESTRICT ] -ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) +ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] RENAME TO <replaceable>new_name</replaceable> -ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) +ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER } -ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) +ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] SET SCHEMA <replaceable>new_schema</replaceable> -ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) +ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] DEPENDS ON EXTENSION <replaceable>extension_name</replaceable> <phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase> @@ -75,7 +75,8 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="paramet <term><replaceable class="parameter">name</replaceable></term> <listitem> <para> - The name (optionally schema-qualified) of an existing function. + The name (optionally schema-qualified) of an existing function. If no + argument list is specified, the name must be unique in its schema. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/alter_opfamily.sgml b/doc/src/sgml/ref/alter_opfamily.sgml index 4511c7f7b24..0bafe5b8f80 100644 --- a/doc/src/sgml/ref/alter_opfamily.sgml +++ b/doc/src/sgml/ref/alter_opfamily.sgml @@ -25,7 +25,7 @@ ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class=" { OPERATOR <replaceable class="parameter">strategy_number</replaceable> <replaceable class="parameter">operator_name</replaceable> ( <replaceable class="parameter">op_type</replaceable>, <replaceable class="parameter">op_type</replaceable> ) [ FOR SEARCH | FOR ORDER BY <replaceable class="parameter">sort_family_name</replaceable> ] | FUNCTION <replaceable class="parameter">support_number</replaceable> [ ( <replaceable class="parameter">op_type</replaceable> [ , <replaceable class="parameter">op_type</replaceable> ] ) ] - <replaceable class="parameter">function_name</replaceable> ( <replaceable class="parameter">argument_type</replaceable> [, ...] ) + <replaceable class="parameter">function_name</replaceable> [ ( <replaceable class="parameter">argument_type</replaceable> [, ...] ) ] } [, ... ] ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> DROP @@ -195,8 +195,9 @@ ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class=" <term><replaceable class="parameter">function_name</replaceable></term> <listitem> <para> - The name (optionally schema-qualified) of a function that is an - index method support procedure for the operator family. + The name (optionally schema-qualified) of a function that is an index + method support procedure for the operator family. If no argument list + is specified, the name must be unique in its schema. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml index c1cf587cb29..7483c8c03fc 100644 --- a/doc/src/sgml/ref/comment.sgml +++ b/doc/src/sgml/ref/comment.sgml @@ -37,7 +37,7 @@ COMMENT ON EVENT TRIGGER <replaceable class="PARAMETER">object_name</replaceable> | FOREIGN DATA WRAPPER <replaceable class="PARAMETER">object_name</replaceable> | FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> | - FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) | + FUNCTION <replaceable class="PARAMETER">function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] | INDEX <replaceable class="PARAMETER">object_name</replaceable> | LARGE OBJECT <replaceable class="PARAMETER">large_object_oid</replaceable> | MATERIALIZED VIEW <replaceable class="PARAMETER">object_name</replaceable> | diff --git a/doc/src/sgml/ref/create_cast.sgml b/doc/src/sgml/ref/create_cast.sgml index 11266755e56..a7d13edc22b 100644 --- a/doc/src/sgml/ref/create_cast.sgml +++ b/doc/src/sgml/ref/create_cast.sgml @@ -19,7 +19,7 @@ <refsynopsisdiv> <synopsis> CREATE CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) - WITH FUNCTION <replaceable>function_name</replaceable> (<replaceable>argument_type</replaceable> [, ...]) + WITH FUNCTION <replaceable>function_name</replaceable> [ (<replaceable>argument_type</replaceable> [, ...]) ] [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) @@ -192,7 +192,7 @@ SELECT CAST ( 2 AS numeric ) + 4.0; </varlistentry> <varlistentry> - <term><replaceable>function_name</replaceable>(<replaceable>argument_type</replaceable> [, ...])</term> + <term><literal><replaceable>function_name</replaceable>[(<replaceable>argument_type</replaceable> [, ...])]</literal></term> <listitem> <para> @@ -200,6 +200,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0; be schema-qualified. If it is not, the function will be looked up in the schema search path. The function's result data type must match the target type of the cast. Its arguments are discussed below. + If no argument list is specified, the function name must be unique in + its schema. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/create_transform.sgml b/doc/src/sgml/ref/create_transform.sgml index f44ee89d33c..647c3b9f057 100644 --- a/doc/src/sgml/ref/create_transform.sgml +++ b/doc/src/sgml/ref/create_transform.sgml @@ -19,8 +19,8 @@ <refsynopsisdiv> <synopsis> CREATE [ OR REPLACE ] TRANSFORM FOR <replaceable>type_name</replaceable> LANGUAGE <replaceable>lang_name</replaceable> ( - FROM SQL WITH FUNCTION <replaceable>from_sql_function_name</replaceable> (<replaceable>argument_type</replaceable> [, ...]), - TO SQL WITH FUNCTION <replaceable>to_sql_function_name</replaceable> (<replaceable>argument_type</replaceable> [, ...]) + FROM SQL WITH FUNCTION <replaceable>from_sql_function_name</replaceable> [ (<replaceable>argument_type</replaceable> [, ...]) ], + TO SQL WITH FUNCTION <replaceable>to_sql_function_name</replaceable> [ (<replaceable>argument_type</replaceable> [, ...]) ] ); </synopsis> </refsynopsisdiv> @@ -104,7 +104,7 @@ CREATE [ OR REPLACE ] TRANSFORM FOR <replaceable>type_name</replaceable> LANGUAG </varlistentry> <varlistentry> - <term><replaceable>from_sql_function_name</replaceable>(<replaceable>argument_type</replaceable> [, ...])</term> + <term><literal><replaceable>from_sql_function_name</replaceable>[(<replaceable>argument_type</replaceable> [, ...])]</literal></term> <listitem> <para> @@ -116,12 +116,14 @@ CREATE [ OR REPLACE ] TRANSFORM FOR <replaceable>type_name</replaceable> LANGUAG SQL-level function returning <type>internal</type> without at least one argument of type <type>internal</type>.) The actual return value will be something specific to the language implementation. + If no argument list is specified, the function name must be unique in + its schema. </para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>to_sql_function_name</replaceable>(<replaceable>argument_type</replaceable> [, ...])</term> + <term><literal><replaceable>to_sql_function_name</replaceable>[(<replaceable>argument_type</replaceable> [, ...])]</literal></term> <listitem> <para> @@ -130,6 +132,8 @@ CREATE [ OR REPLACE ] TRANSFORM FOR <replaceable>type_name</replaceable> LANGUAG <type>internal</type> and return the type that is the type for the transform. The actual argument value will be something specific to the language implementation. + If no argument list is specified, the function name must be unique in + its schema. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/drop_function.sgml b/doc/src/sgml/ref/drop_function.sgml index 5969b084b44..0aa984528d3 100644 --- a/doc/src/sgml/ref/drop_function.sgml +++ b/doc/src/sgml/ref/drop_function.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation <refsynopsisdiv> <synopsis> -DROP FUNCTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) [, ...] +DROP FUNCTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] [, ...] [ CASCADE | RESTRICT ] </synopsis> </refsynopsisdiv> @@ -56,7 +56,8 @@ DROP FUNCTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ( <term><replaceable class="parameter">name</replaceable></term> <listitem> <para> - The name (optionally schema-qualified) of an existing function. + The name (optionally schema-qualified) of an existing function. If no + argument list is specified, the name must be unique in its schema. </para> </listitem> </varlistentry> @@ -141,14 +142,40 @@ DROP FUNCTION sqrt(integer); <programlisting> DROP FUNCTION sqrt(integer), sqrt(bigint); </programlisting></para> + + <para> + If the function name is unique in its schema, it can be referred to without + an argument list: +<programlisting> +DROP FUNCTION update_employee_salaries; +</programlisting> + Note that this is different from +<programlisting> +DROP FUNCTION update_employee_salaries(); +</programlisting> + which refers to a function with zero arguments, whereas the first variant + can refer to a function with any number of arguments, including zero, as + long as the name is unique. + </para> </refsect1> <refsect1 id="SQL-DROPFUNCTION-compatibility"> <title>Compatibility</title> <para> - A <command>DROP FUNCTION</command> statement is defined in the SQL - standard, but it is not compatible with this command. + This command conforms to the SQL standard, with + these <productname>PostgreSQL</productname> extensions: + <itemizedlist> + <listitem> + <para>The standard only allows one function to be dropped per command.</para> + </listitem> + <listitem> + <para>The <literal>IF EXISTS</literal> option</para> + </listitem> + <listitem> + <para>The ability to specify argument modes and names</para> + </listitem> + </itemizedlist> </para> </refsect1> diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index d8ca39f869e..9fb4c2fd7e3 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -55,7 +55,7 @@ GRANT { USAGE | ALL [ PRIVILEGES ] } TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] GRANT { EXECUTE | ALL [ PRIVILEGES ] } - ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...] + ON { FUNCTION <replaceable>function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) ] [, ...] | ALL FUNCTIONS IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] } TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index fc00129620b..ce532543f0b 100644 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -70,7 +70,7 @@ REVOKE [ GRANT OPTION FOR ] REVOKE [ GRANT OPTION FOR ] { EXECUTE | ALL [ PRIVILEGES ] } - ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...] + ON { FUNCTION <replaceable>function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) ] [, ...] | ALL FUNCTIONS IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/security_label.sgml b/doc/src/sgml/ref/security_label.sgml index 998fe3b7c03..afd86aff3a0 100644 --- a/doc/src/sgml/ref/security_label.sgml +++ b/doc/src/sgml/ref/security_label.sgml @@ -30,7 +30,7 @@ SECURITY LABEL [ FOR <replaceable class="PARAMETER">provider</replaceable> ] ON DOMAIN <replaceable class="PARAMETER">object_name</replaceable> | EVENT TRIGGER <replaceable class="PARAMETER">object_name</replaceable> | FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> - FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) | + FUNCTION <replaceable class="PARAMETER">function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ] | LARGE OBJECT <replaceable class="PARAMETER">large_object_oid</replaceable> | MATERIALIZED VIEW <replaceable class="PARAMETER">object_name</replaceable> | [ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">object_name</replaceable> | 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; |