1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-15 05:46:52 +03:00

Provide more-specific error details/hints for function lookup failures.

Up to now we've contented ourselves with a one-size-fits-all error
hint when we fail to find any match to a function or procedure call.
That was mostly okay in the beginning, but it was never great, and
since the introduction of named arguments it's really not adequate.
We at least ought to distinguish "function name doesn't exist" from
"function name exists, but not with those argument names".  And the
rules for named-argument matching are arcane enough that some more
detail seems warranted if we match the argument names but the call
still doesn't work.

This patch creates a framework for dealing with these problems:
FuncnameGetCandidates and related code will now pass back a bitmask of
flags showing how far the match succeeded.  This allows a considerable
amount of granularity in the reports.  The set-bits-in-a-bitmask
approach means that when there are multiple candidate functions, the
report will reflect the match(es) that got the furthest, which seems
correct.  Also, we can avoid mentioning "maybe add casts" unless
failure to match argument types is actually the issue.

Extend the same return-a-bitmask approach to OpernameGetCandidates.
The issues around argument names don't apply to operator syntax,
but it still seems worth distinguishing between "there is no
operator of that name" and "we couldn't match the argument types".

While at it, adjust these messages and related ones to more strictly
separate "detail" from "hint", following our message style guidelines'
distinction between those.

Reported-by: Dominique Devienne <ddevienne@gmail.com>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Discussion: https://postgr.es/m/1756041.1754616558@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2025-09-16 12:17:02 -04:00
parent c7b0cb367d
commit 83a5641945
44 changed files with 573 additions and 151 deletions

View File

@@ -4609,11 +4609,13 @@ SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1;
-- with that remote type -- with that remote type
SELECT * FROM ft1 WHERE c8 LIKE 'foo' LIMIT 1; -- ERROR SELECT * FROM ft1 WHERE c8 LIKE 'foo' LIMIT 1; -- ERROR
ERROR: operator does not exist: public.user_enum ~~ unknown ERROR: operator does not exist: public.user_enum ~~ unknown
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 ~~ 'foo')) LIMIT 1::bigint CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 ~~ 'foo')) LIMIT 1::bigint
SELECT * FROM ft1 WHERE c8::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down SELECT * FROM ft1 WHERE c8::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down
ERROR: operator does not exist: public.user_enum ~~ unknown ERROR: operator does not exist: public.user_enum ~~ unknown
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 ~~ 'foo')) LIMIT 1::bigint CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 ~~ 'foo')) LIMIT 1::bigint
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum; ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
-- =================================================================== -- ===================================================================

View File

@@ -153,11 +153,12 @@ ereport(ERROR,
errmsg("function %s is not unique", errmsg("function %s is not unique",
func_signature_string(funcname, nargs, func_signature_string(funcname, nargs,
NIL, actual_arg_types)), NIL, actual_arg_types)),
errhint("Unable to choose a best candidate function. " errdetail("Could not choose a best candidate function."),
"You might need to add explicit typecasts.")); errhint("You might need to add explicit type casts."));
</programlisting> </programlisting>
This illustrates the use of format codes to embed run-time values into This illustrates the use of format codes to embed run-time values into
a message text. Also, an optional <quote>hint</quote> message is provided. a message text. Also, optional <quote>detail</quote>
and <quote>hint</quote> messages are provided.
The auxiliary function calls can be written in any order, but The auxiliary function calls can be written in any order, but
conventionally <function>errcode</function> conventionally <function>errcode</function>
and <function>errmsg</function> appear first. and <function>errmsg</function> appear first.

View File

@@ -465,9 +465,9 @@ try a similar case with <literal>~</literal>, we get:
<screen> <screen>
SELECT ~ '20' AS "negation"; SELECT ~ '20' AS "negation";
ERROR: operator is not unique: ~ "unknown" ERROR: operator is not unique: ~ unknown
HINT: Could not choose a best candidate operator. You might need to add DETAIL: Could not choose a best candidate operator.
explicit type casts. HINT: You might need to add explicit type casts.
</screen> </screen>
This happens because the system cannot decide which of the several This happens because the system cannot decide which of the several
possible <literal>~</literal> operators should be preferred. We can help possible <literal>~</literal> operators should be preferred. We can help
@@ -901,8 +901,8 @@ the parser will try to convert that to <type>text</type>:
<screen> <screen>
SELECT substr(1234, 3); SELECT substr(1234, 3);
ERROR: function substr(integer, integer) does not exist ERROR: function substr(integer, integer) does not exist
HINT: No function matches the given name and argument types. You might need DETAIL: No function of that name accepts the given argument types.
to add explicit type casts. HINT: You might need to add explicit type casts.
</screen> </screen>
This does not work because <type>integer</type> does not have an implicit cast This does not work because <type>integer</type> does not have an implicit cast

View File

@@ -232,7 +232,7 @@ static void RemoveTempRelationsCallback(int code, Datum arg);
static void InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue); static void InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue);
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
bool include_out_arguments, int pronargs, bool include_out_arguments, int pronargs,
int **argnumbers); int **argnumbers, int *fgc_flags);
/* /*
* Recomputing the namespace path can be costly when done frequently, such as * Recomputing the namespace path can be costly when done frequently, such as
@@ -1117,15 +1117,15 @@ TypeIsVisibleExt(Oid typid, bool *is_missing)
/* /*
* FuncnameGetCandidates * FuncnameGetCandidates
* Given a possibly-qualified function name and argument count, * Given a possibly-qualified routine name, argument count, and arg names,
* retrieve a list of the possible matches. * retrieve a list of the possible matches.
* *
* If nargs is -1, we return all functions matching the given name, * If nargs is -1, we return all routines matching the given name,
* regardless of argument count. (argnames must be NIL, and expand_variadic * regardless of argument count. (argnames must be NIL, and expand_variadic
* and expand_defaults must be false, in this case.) * and expand_defaults must be false, in this case.)
* *
* If argnames isn't NIL, we are considering a named- or mixed-notation call, * If argnames isn't NIL, we are considering a named- or mixed-notation call,
* and only functions having all the listed argument names will be returned. * and only routines having all the listed argument names will be returned.
* (We assume that length(argnames) <= nargs and all the passed-in names are * (We assume that length(argnames) <= nargs and all the passed-in names are
* distinct.) The returned structs will include an argnumbers array showing * distinct.) The returned structs will include an argnumbers array showing
* the actual argument index for each logical argument position. * the actual argument index for each logical argument position.
@@ -1183,14 +1183,21 @@ TypeIsVisibleExt(Oid typid, bool *is_missing)
* The caller might end up discarding such an entry anyway, but if it selects * The caller might end up discarding such an entry anyway, but if it selects
* such an entry it should react as though the call were ambiguous. * such an entry it should react as though the call were ambiguous.
* *
* If missing_ok is true, an empty list (NULL) is returned if the name was * We return an empty list (NULL) if no suitable matches can be found.
* schema-qualified with a schema that does not exist. Likewise if no * If the function name was schema-qualified with a schema that does not
* candidate is found for other reasons. * exist, then we return an empty list if missing_ok is true and otherwise
* throw an error. (missing_ok does not affect the behavior otherwise.)
*
* The output argument *fgc_flags is filled with a bitmask indicating how
* far we were able to match the supplied information. This is not of much
* interest if any candidates were found, but if not, it can help callers
* produce an on-point error message.
*/ */
FuncCandidateList FuncCandidateList
FuncnameGetCandidates(List *names, int nargs, List *argnames, FuncnameGetCandidates(List *names, int nargs, List *argnames,
bool expand_variadic, bool expand_defaults, bool expand_variadic, bool expand_defaults,
bool include_out_arguments, bool missing_ok) bool include_out_arguments, bool missing_ok,
int *fgc_flags)
{ {
FuncCandidateList resultList = NULL; FuncCandidateList resultList = NULL;
bool any_special = false; bool any_special = false;
@@ -1203,15 +1210,20 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
/* check for caller error */ /* check for caller error */
Assert(nargs >= 0 || !(expand_variadic | expand_defaults)); Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
/* initialize output fgc_flags to empty */
*fgc_flags = 0;
/* deconstruct the name list */ /* deconstruct the name list */
DeconstructQualifiedName(names, &schemaname, &funcname); DeconstructQualifiedName(names, &schemaname, &funcname);
if (schemaname) if (schemaname)
{ {
/* use exact schema given */ /* use exact schema given */
*fgc_flags |= FGC_SCHEMA_GIVEN; /* report that a schema is given */
namespaceId = LookupExplicitNamespace(schemaname, missing_ok); namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
if (!OidIsValid(namespaceId)) if (!OidIsValid(namespaceId))
return NULL; return NULL;
*fgc_flags |= FGC_SCHEMA_EXISTS; /* report that the schema exists */
} }
else else
{ {
@@ -1237,6 +1249,8 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
int *argnumbers = NULL; int *argnumbers = NULL;
FuncCandidateList newResult; FuncCandidateList newResult;
*fgc_flags |= FGC_NAME_EXISTS; /* the name is present in pg_proc */
if (OidIsValid(namespaceId)) if (OidIsValid(namespaceId))
{ {
/* Consider only procs in specified namespace */ /* Consider only procs in specified namespace */
@@ -1262,6 +1276,8 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
continue; /* proc is not in search path */ continue; /* proc is not in search path */
} }
*fgc_flags |= FGC_NAME_VISIBLE; /* routine is in the right schema */
/* /*
* If we are asked to match to OUT arguments, then use the * If we are asked to match to OUT arguments, then use the
* proallargtypes array (which includes those); otherwise use * proallargtypes array (which includes those); otherwise use
@@ -1296,16 +1312,6 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
/* /*
* Call uses named or mixed notation * Call uses named or mixed notation
* *
* Named or mixed notation can match a variadic function only if
* expand_variadic is off; otherwise there is no way to match the
* presumed-nameless parameters expanded from the variadic array.
*/
if (OidIsValid(procform->provariadic) && expand_variadic)
continue;
va_elem_type = InvalidOid;
variadic = false;
/*
* Check argument count. * Check argument count.
*/ */
Assert(nargs >= 0); /* -1 not supported with argnames */ Assert(nargs >= 0); /* -1 not supported with argnames */
@@ -1324,12 +1330,33 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
if (pronargs != nargs && !use_defaults) if (pronargs != nargs && !use_defaults)
continue; continue;
/* We found a routine with a suitable number of arguments */
*fgc_flags |= FGC_ARGCOUNT_MATCH;
/* Check for argument name match, generate positional mapping */ /* Check for argument name match, generate positional mapping */
if (!MatchNamedCall(proctup, nargs, argnames, if (!MatchNamedCall(proctup, nargs, argnames,
include_out_arguments, pronargs, include_out_arguments, pronargs,
&argnumbers)) &argnumbers, fgc_flags))
continue; continue;
/*
* Named or mixed notation can match a variadic function only if
* expand_variadic is off; otherwise there is no way to match the
* presumed-nameless parameters expanded from the variadic array.
* However, we postpone the check until here because we want to
* perform argument name matching anyway (using the variadic array
* argument's name). This allows us to give an on-point error
* message if the user forgets to say VARIADIC in what would have
* been a valid call with it.
*/
if (OidIsValid(procform->provariadic) && expand_variadic)
continue;
va_elem_type = InvalidOid;
variadic = false;
/* We found a fully-valid call using argument names */
*fgc_flags |= FGC_ARGNAMES_VALID;
/* Named argument matching is always "special" */ /* Named argument matching is always "special" */
any_special = true; any_special = true;
} }
@@ -1371,6 +1398,9 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
/* Ignore if it doesn't match requested argument count */ /* Ignore if it doesn't match requested argument count */
if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults) if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
continue; continue;
/* We found a routine with a suitable number of arguments */
*fgc_flags |= FGC_ARGCOUNT_MATCH;
} }
/* /*
@@ -1579,11 +1609,13 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
* the mapping from call argument positions to actual function argument * the mapping from call argument positions to actual function argument
* numbers. Defaulted arguments are included in this map, at positions * numbers. Defaulted arguments are included in this map, at positions
* after the last supplied argument. * after the last supplied argument.
*
* We also add flag bits to *fgc_flags reporting on how far the match got.
*/ */
static bool static bool
MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
bool include_out_arguments, int pronargs, bool include_out_arguments, int pronargs,
int **argnumbers) int **argnumbers, int *fgc_flags)
{ {
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup); Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
int numposargs = nargs - list_length(argnames); int numposargs = nargs - list_length(argnames);
@@ -1592,6 +1624,7 @@ MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
char **p_argnames; char **p_argnames;
char *p_argmodes; char *p_argmodes;
bool arggiven[FUNC_MAX_ARGS]; bool arggiven[FUNC_MAX_ARGS];
bool arg_filled_twice = false;
bool isnull; bool isnull;
int ap; /* call args position */ int ap; /* call args position */
int pp; /* proargs position */ int pp; /* proargs position */
@@ -1645,9 +1678,9 @@ MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
continue; continue;
if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0) if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
{ {
/* fail if argname matches a positional argument */ /* note if argname matches a positional argument */
if (arggiven[pp]) if (arggiven[pp])
return false; arg_filled_twice = true;
arggiven[pp] = true; arggiven[pp] = true;
(*argnumbers)[ap] = pp; (*argnumbers)[ap] = pp;
found = true; found = true;
@@ -1664,6 +1697,16 @@ MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
Assert(ap == nargs); /* processed all actual parameters */ Assert(ap == nargs); /* processed all actual parameters */
/* If we get here, the function did match all the supplied argnames */
*fgc_flags |= FGC_ARGNAMES_MATCH;
/* ... however, some of them might have been placed wrong */
if (arg_filled_twice)
return false; /* some argname matched a positional argument */
/* If we get here, the call doesn't have invalid mixed notation */
*fgc_flags |= FGC_ARGNAMES_NONDUP;
/* Check for default arguments */ /* Check for default arguments */
if (nargs < pronargs) if (nargs < pronargs)
{ {
@@ -1682,6 +1725,9 @@ MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
Assert(ap == pronargs); /* processed all function parameters */ Assert(ap == pronargs); /* processed all function parameters */
/* If we get here, the call supplies all the required arguments */
*fgc_flags |= FGC_ARGNAMES_ALL;
return true; return true;
} }
@@ -1745,11 +1791,13 @@ FunctionIsVisibleExt(Oid funcid, bool *is_missing)
char *proname = NameStr(procform->proname); char *proname = NameStr(procform->proname);
int nargs = procform->pronargs; int nargs = procform->pronargs;
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
visible = false; visible = false;
clist = FuncnameGetCandidates(list_make1(makeString(proname)), clist = FuncnameGetCandidates(list_make1(makeString(proname)),
nargs, NIL, false, false, false, false); nargs, NIL, false, false, false, false,
&fgc_flags);
for (; clist; clist = clist->next) for (; clist; clist = clist->next)
{ {
@@ -1882,9 +1930,20 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
* *
* The returned items always have two args[] entries --- the first will be * The returned items always have two args[] entries --- the first will be
* InvalidOid for a prefix oprkind. nargs is always 2, too. * InvalidOid for a prefix oprkind. nargs is always 2, too.
*
* We return an empty list (NULL) if no suitable matches can be found. If the
* operator name was schema-qualified with a schema that does not exist, then
* we return an empty list if missing_schema_ok is true and otherwise throw an
* error. (missing_schema_ok does not affect the behavior otherwise.)
*
* The output argument *fgc_flags is filled with a bitmask indicating how
* far we were able to match the supplied information. This is not of much
* interest if any candidates were found, but if not, it can help callers
* produce an on-point error message.
*/ */
FuncCandidateList FuncCandidateList
OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok) OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok,
int *fgc_flags)
{ {
FuncCandidateList resultList = NULL; FuncCandidateList resultList = NULL;
char *resultSpace = NULL; char *resultSpace = NULL;
@@ -1895,15 +1954,20 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
CatCList *catlist; CatCList *catlist;
int i; int i;
/* initialize output fgc_flags to empty */
*fgc_flags = 0;
/* deconstruct the name list */ /* deconstruct the name list */
DeconstructQualifiedName(names, &schemaname, &opername); DeconstructQualifiedName(names, &schemaname, &opername);
if (schemaname) if (schemaname)
{ {
/* use exact schema given */ /* use exact schema given */
*fgc_flags |= FGC_SCHEMA_GIVEN; /* report that a schema is given */
namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok); namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
if (missing_schema_ok && !OidIsValid(namespaceId)) if (!OidIsValid(namespaceId))
return NULL; return NULL;
*fgc_flags |= FGC_SCHEMA_EXISTS; /* report that the schema exists */
} }
else else
{ {
@@ -1941,6 +2005,8 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
if (oprkind && operform->oprkind != oprkind) if (oprkind && operform->oprkind != oprkind)
continue; continue;
*fgc_flags |= FGC_NAME_EXISTS; /* the name is present in pg_operator */
if (OidIsValid(namespaceId)) if (OidIsValid(namespaceId))
{ {
/* Consider only opers in specified namespace */ /* Consider only opers in specified namespace */
@@ -2014,6 +2080,8 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
} }
} }
*fgc_flags |= FGC_NAME_VISIBLE; /* operator is in the right schema */
/* /*
* Okay to add it to result list * Okay to add it to result list
*/ */

View File

@@ -836,6 +836,7 @@ lookup_agg_function(List *fnName,
Oid vatype; Oid vatype;
Oid *true_oid_array; Oid *true_oid_array;
FuncDetailCode fdresult; FuncDetailCode fdresult;
int fgc_flags;
AclResult aclresult; AclResult aclresult;
int i; int i;
@@ -848,6 +849,7 @@ lookup_agg_function(List *fnName,
*/ */
fdresult = func_get_detail(fnName, NIL, NIL, fdresult = func_get_detail(fnName, NIL, NIL,
nargs, input_types, false, false, false, nargs, input_types, false, false, false,
&fgc_flags,
&fnOid, rettype, &retset, &fnOid, rettype, &retset,
&nvargs, &vatype, &nvargs, &vatype,
&true_oid_array, NULL); &true_oid_array, NULL);

View File

@@ -42,6 +42,8 @@ typedef enum
FUNCLOOKUP_AMBIGUOUS, FUNCLOOKUP_AMBIGUOUS,
} FuncLookupError; } FuncLookupError;
static int func_lookup_failure_details(int fgc_flags, List *argnames,
bool proc_call);
static void unify_hypothetical_args(ParseState *pstate, static void unify_hypothetical_args(ParseState *pstate,
List *fargs, int numAggregatedArgs, List *fargs, int numAggregatedArgs,
Oid *actual_arg_types, Oid *declared_arg_types); Oid *actual_arg_types, Oid *declared_arg_types);
@@ -115,6 +117,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
int nvargs; int nvargs;
Oid vatype; Oid vatype;
FuncDetailCode fdresult; FuncDetailCode fdresult;
int fgc_flags;
char aggkind = 0; char aggkind = 0;
ParseCallbackState pcbstate; ParseCallbackState pcbstate;
@@ -266,6 +269,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
fdresult = func_get_detail(funcname, fargs, argnames, nargs, fdresult = func_get_detail(funcname, fargs, argnames, nargs,
actual_arg_types, actual_arg_types,
!func_variadic, true, proc_call, !func_variadic, true, proc_call,
&fgc_flags,
&funcid, &rettype, &retset, &funcid, &rettype, &retset,
&nvargs, &vatype, &nvargs, &vatype,
&declared_arg_types, &argdefaults); &declared_arg_types, &argdefaults);
@@ -563,8 +567,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
errmsg("procedure %s is not unique", errmsg("procedure %s is not unique",
func_signature_string(funcname, nargs, argnames, func_signature_string(funcname, nargs, argnames,
actual_arg_types)), actual_arg_types)),
errhint("Could not choose a best candidate procedure. " errdetail("Could not choose a best candidate procedure."),
"You might need to add explicit type casts."), errhint("You might need to add explicit type casts."),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
else else
ereport(ERROR, ereport(ERROR,
@@ -572,8 +576,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
errmsg("function %s is not unique", errmsg("function %s is not unique",
func_signature_string(funcname, nargs, argnames, func_signature_string(funcname, nargs, argnames,
actual_arg_types)), actual_arg_types)),
errhint("Could not choose a best candidate function. " errdetail("Could not choose a best candidate function."),
"You might need to add explicit type casts."), errhint("You might need to add explicit type casts."),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
} }
else else
@@ -601,7 +605,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
/* /*
* No function, and no column either. Since we're dealing with * No function, and no column either. Since we're dealing with
* function notation, report "function does not exist". * function notation, report "function/procedure does not exist".
* Depending on what was returned in fgc_flags, we can add some color
* to that with detail or hint messages.
*/ */
if (list_length(agg_order) > 1 && !agg_within_group) if (list_length(agg_order) > 1 && !agg_within_group)
{ {
@@ -611,8 +617,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
errmsg("function %s does not exist", errmsg("function %s does not exist",
func_signature_string(funcname, nargs, argnames, func_signature_string(funcname, nargs, argnames,
actual_arg_types)), actual_arg_types)),
errhint("No aggregate function matches the given name and argument types. " errdetail("No aggregate function matches the given name and argument types."),
"Perhaps you misplaced ORDER BY; ORDER BY must appear " errhint("Perhaps you misplaced ORDER BY; ORDER BY must appear "
"after all regular arguments of the aggregate."), "after all regular arguments of the aggregate."),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
} }
@@ -622,8 +628,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
errmsg("procedure %s does not exist", errmsg("procedure %s does not exist",
func_signature_string(funcname, nargs, argnames, func_signature_string(funcname, nargs, argnames,
actual_arg_types)), actual_arg_types)),
errhint("No procedure matches the given name and argument types. " func_lookup_failure_details(fgc_flags, argnames,
"You might need to add explicit type casts."), proc_call),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
else else
ereport(ERROR, ereport(ERROR,
@@ -631,8 +637,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
errmsg("function %s does not exist", errmsg("function %s does not exist",
func_signature_string(funcname, nargs, argnames, func_signature_string(funcname, nargs, argnames,
actual_arg_types)), actual_arg_types)),
errhint("No function matches the given name and argument types. " func_lookup_failure_details(fgc_flags, argnames,
"You might need to add explicit type casts."), proc_call),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
} }
@@ -905,6 +911,104 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
return retval; return retval;
} }
/*
* Interpret the fgc_flags and issue a suitable detail or hint message.
*
* Helper function to reduce code duplication while throwing a
* function-not-found error.
*/
static int
func_lookup_failure_details(int fgc_flags, List *argnames, bool proc_call)
{
/*
* If not FGC_NAME_VISIBLE, we shouldn't raise the question of whether the
* arguments are wrong. If the function name was not schema-qualified,
* it's helpful to distinguish between doesn't-exist-anywhere and
* not-in-search-path; but if it was, there's really nothing to add to the
* basic "function/procedure %s does not exist" message.
*
* Note: we passed missing_ok = false to FuncnameGetCandidates, so there's
* no need to consider FGC_SCHEMA_EXISTS here: we'd have already thrown an
* error if an explicitly-given schema doesn't exist.
*/
if (!(fgc_flags & FGC_NAME_VISIBLE))
{
if (fgc_flags & FGC_SCHEMA_GIVEN)
return 0; /* schema-qualified name */
else if (!(fgc_flags & FGC_NAME_EXISTS))
{
if (proc_call)
return errdetail("There is no procedure of that name.");
else
return errdetail("There is no function of that name.");
}
else
{
if (proc_call)
return errdetail("A procedure of that name exists, but it is not in the search_path.");
else
return errdetail("A function of that name exists, but it is not in the search_path.");
}
}
/*
* Next, complain if nothing had the right number of arguments. (This
* takes precedence over wrong-argnames cases because we won't even look
* at the argnames unless there's a workable number of arguments.)
*/
if (!(fgc_flags & FGC_ARGCOUNT_MATCH))
{
if (proc_call)
return errdetail("No procedure of that name accepts the given number of arguments.");
else
return errdetail("No function of that name accepts the given number of arguments.");
}
/*
* If there are argnames, and we failed to match them, again we should
* mention that and not bring up the argument types.
*/
if (argnames != NIL && !(fgc_flags & FGC_ARGNAMES_MATCH))
{
if (proc_call)
return errdetail("No procedure of that name accepts the given argument names.");
else
return errdetail("No function of that name accepts the given argument names.");
}
/*
* We could have matched all the given argnames and still not have had a
* valid call, either because of improper use of mixed notation, or
* because of missing arguments, or because the user misused VARIADIC. The
* rules about named-argument matching are finicky enough that it's worth
* trying to be specific about the problem. (The messages here are chosen
* with full knowledge of the steps that namespace.c uses while checking a
* potential match.)
*/
if (argnames != NIL && !(fgc_flags & FGC_ARGNAMES_NONDUP))
return errdetail("In the closest available match, "
"an argument was specified both positionally and by name.");
if (argnames != NIL && !(fgc_flags & FGC_ARGNAMES_ALL))
return errdetail("In the closest available match, "
"not all required arguments were supplied.");
if (argnames != NIL && !(fgc_flags & FGC_ARGNAMES_VALID))
return errhint("This call would be correct if the variadic array were labeled VARIADIC and placed last.");
if (fgc_flags & FGC_VARIADIC_FAIL)
return errhint("The VARIADIC parameter must be placed last, even when using argument names.");
/*
* Otherwise, the problem must be incorrect argument types.
*/
if (proc_call)
(void) errdetail("No procedure of that name accepts the given argument types.");
else
(void) errdetail("No function of that name accepts the given argument types.");
return errhint("You might need to add explicit type casts.");
}
/* func_match_argtypes() /* func_match_argtypes()
* *
@@ -1372,9 +1476,14 @@ func_select_candidate(int nargs,
* 1) check for possible interpretation as a type coercion request * 1) check for possible interpretation as a type coercion request
* 2) apply the ambiguous-function resolution rules * 2) apply the ambiguous-function resolution rules
* *
* Return values *funcid through *true_typeids receive info about the function. * If there is no match at all, we return FUNCDETAIL_NOTFOUND, and *fgc_flags
* If argdefaults isn't NULL, *argdefaults receives a list of any default * is filled with some flags that may be useful for issuing an on-point error
* argument expressions that need to be added to the given arguments. * message (see FuncnameGetCandidates).
*
* On success, return values *funcid through *true_typeids receive info about
* the function. If argdefaults isn't NULL, *argdefaults receives a list of
* any default argument expressions that need to be added to the given
* arguments.
* *
* When processing a named- or mixed-notation call (ie, fargnames isn't NIL), * When processing a named- or mixed-notation call (ie, fargnames isn't NIL),
* the returned true_typeids and argdefaults are ordered according to the * the returned true_typeids and argdefaults are ordered according to the
@@ -1400,6 +1509,7 @@ func_get_detail(List *funcname,
bool expand_variadic, bool expand_variadic,
bool expand_defaults, bool expand_defaults,
bool include_out_arguments, bool include_out_arguments,
int *fgc_flags, /* return value */
Oid *funcid, /* return value */ Oid *funcid, /* return value */
Oid *rettype, /* return value */ Oid *rettype, /* return value */
bool *retset, /* return value */ bool *retset, /* return value */
@@ -1424,7 +1534,8 @@ func_get_detail(List *funcname,
/* Get list of possible candidates from namespace search */ /* Get list of possible candidates from namespace search */
raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames, raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames,
expand_variadic, expand_defaults, expand_variadic, expand_defaults,
include_out_arguments, false); include_out_arguments, false,
fgc_flags);
/* /*
* Quickly check if there is an exact match to the input datatypes (there * Quickly check if there is an exact match to the input datatypes (there
@@ -1594,7 +1705,10 @@ func_get_detail(List *funcname,
*/ */
if (fargnames != NIL && !expand_variadic && nargs > 0 && if (fargnames != NIL && !expand_variadic && nargs > 0 &&
best_candidate->argnumbers[nargs - 1] != nargs - 1) best_candidate->argnumbers[nargs - 1] != nargs - 1)
{
*fgc_flags |= FGC_VARIADIC_FAIL;
return FUNCDETAIL_NOTFOUND; return FUNCDETAIL_NOTFOUND;
}
*funcid = best_candidate->oid; *funcid = best_candidate->oid;
*nvargs = best_candidate->nvargs; *nvargs = best_candidate->nvargs;
@@ -2053,6 +2167,7 @@ LookupFuncNameInternal(ObjectType objtype, List *funcname,
{ {
Oid result = InvalidOid; Oid result = InvalidOid;
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
/* NULL argtypes allowed for nullary functions only */ /* NULL argtypes allowed for nullary functions only */
Assert(argtypes != NULL || nargs == 0); Assert(argtypes != NULL || nargs == 0);
@@ -2062,7 +2177,8 @@ LookupFuncNameInternal(ObjectType objtype, List *funcname,
/* Get list of candidate objects */ /* Get list of candidate objects */
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false,
include_out_arguments, missing_ok); include_out_arguments, missing_ok,
&fgc_flags);
/* Scan list for a match to the arg types (if specified) and the objtype */ /* Scan list for a match to the arg types (if specified) and the objtype */
for (; clist != NULL; clist = clist->next) for (; clist != NULL; clist = clist->next)

View File

@@ -72,7 +72,8 @@ static FuncDetailCode oper_select_candidate(int nargs,
Oid *operOid); Oid *operOid);
static void op_error(ParseState *pstate, List *op, static void op_error(ParseState *pstate, List *op,
Oid arg1, Oid arg2, Oid arg1, Oid arg2,
FuncDetailCode fdresult, int location); FuncDetailCode fdresult, int fgc_flags, int location);
static int oper_lookup_failure_details(int fgc_flags, bool is_unary_op);
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key,
List *opname, Oid ltypeId, Oid rtypeId, List *opname, Oid ltypeId, Oid rtypeId,
int location); int location);
@@ -373,6 +374,7 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
Oid operOid; Oid operOid;
OprCacheKey key; OprCacheKey key;
bool key_ok; bool key_ok;
int fgc_flags = 0;
FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND; FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
HeapTuple tup = NULL; HeapTuple tup = NULL;
@@ -404,7 +406,7 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
FuncCandidateList clist; FuncCandidateList clist;
/* Get binary operators of given name */ /* Get binary operators of given name */
clist = OpernameGetCandidates(opname, 'b', false); clist = OpernameGetCandidates(opname, 'b', false, &fgc_flags);
/* No operators found? Then fail... */ /* No operators found? Then fail... */
if (clist != NULL) if (clist != NULL)
@@ -434,7 +436,8 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
make_oper_cache_entry(&key, operOid); make_oper_cache_entry(&key, operOid);
} }
else if (!noError) else if (!noError)
op_error(pstate, opname, ltypeId, rtypeId, fdresult, location); op_error(pstate, opname, ltypeId, rtypeId,
fdresult, fgc_flags, location);
return (Operator) tup; return (Operator) tup;
} }
@@ -520,6 +523,7 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Oid operOid; Oid operOid;
OprCacheKey key; OprCacheKey key;
bool key_ok; bool key_ok;
int fgc_flags = 0;
FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND; FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
HeapTuple tup = NULL; HeapTuple tup = NULL;
@@ -551,7 +555,7 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
FuncCandidateList clist; FuncCandidateList clist;
/* Get prefix operators of given name */ /* Get prefix operators of given name */
clist = OpernameGetCandidates(op, 'l', false); clist = OpernameGetCandidates(op, 'l', false, &fgc_flags);
/* No operators found? Then fail... */ /* No operators found? Then fail... */
if (clist != NULL) if (clist != NULL)
@@ -585,7 +589,8 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
make_oper_cache_entry(&key, operOid); make_oper_cache_entry(&key, operOid);
} }
else if (!noError) else if (!noError)
op_error(pstate, op, InvalidOid, arg, fdresult, location); op_error(pstate, op, InvalidOid, arg,
fdresult, fgc_flags, location);
return (Operator) tup; return (Operator) tup;
} }
@@ -621,29 +626,67 @@ op_signature_string(List *op, Oid arg1, Oid arg2)
static void static void
op_error(ParseState *pstate, List *op, op_error(ParseState *pstate, List *op,
Oid arg1, Oid arg2, Oid arg1, Oid arg2,
FuncDetailCode fdresult, int location) FuncDetailCode fdresult, int fgc_flags, int location)
{ {
if (fdresult == FUNCDETAIL_MULTIPLE) if (fdresult == FUNCDETAIL_MULTIPLE)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION), (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("operator is not unique: %s", errmsg("operator is not unique: %s",
op_signature_string(op, arg1, arg2)), op_signature_string(op, arg1, arg2)),
errhint("Could not choose a best candidate operator. " errdetail("Could not choose a best candidate operator."),
"You might need to add explicit type casts."), errhint("You might need to add explicit type casts."),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator does not exist: %s", errmsg("operator does not exist: %s",
op_signature_string(op, arg1, arg2)), op_signature_string(op, arg1, arg2)),
(!arg1 || !arg2) ? oper_lookup_failure_details(fgc_flags, (!arg1 || !arg2)),
errhint("No operator matches the given name and argument type. "
"You might need to add an explicit type cast.") :
errhint("No operator matches the given name and argument types. "
"You might need to add explicit type casts."),
parser_errposition(pstate, location))); parser_errposition(pstate, location)));
} }
/*
* Interpret the fgc_flags and issue a suitable detail or hint message.
*/
static int
oper_lookup_failure_details(int fgc_flags, bool is_unary_op)
{
/*
* If not FGC_NAME_VISIBLE, we shouldn't raise the question of whether the
* arguments are wrong. If the operator name was not schema-qualified,
* it's helpful to distinguish between doesn't-exist-anywhere and
* not-in-search-path; but if it was, there's really nothing to add to the
* basic "operator does not exist" message.
*
* Note: we passed missing_ok = false to OpernameGetCandidates, so there's
* no need to consider FGC_SCHEMA_EXISTS here: we'd have already thrown an
* error if an explicitly-given schema doesn't exist.
*/
if (!(fgc_flags & FGC_NAME_VISIBLE))
{
if (fgc_flags & FGC_SCHEMA_GIVEN)
return 0; /* schema-qualified name */
else if (!(fgc_flags & FGC_NAME_EXISTS))
return errdetail("There is no operator of that name.");
else
return errdetail("An operator of that name exists, but it is not in the search_path.");
}
/*
* Otherwise, the problem must be incorrect argument type(s).
*/
if (is_unary_op)
{
(void) errdetail("No operator of that name accepts the given argument type.");
return errhint("You might need to add an explicit type cast.");
}
else
{
(void) errdetail("No operator of that name accepts the given argument types.");
return errhint("You might need to add explicit type casts.");
}
}
/* /*
* make_op() * make_op()
* Operator expression construction. * Operator expression construction.

View File

@@ -71,6 +71,7 @@ regprocin(PG_FUNCTION_ARGS)
RegProcedure result; RegProcedure result;
List *names; List *names;
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
/* Handle "-" or numeric OID */ /* Handle "-" or numeric OID */
if (parseDashOrOid(pro_name_or_oid, &result, escontext)) if (parseDashOrOid(pro_name_or_oid, &result, escontext))
@@ -93,7 +94,8 @@ regprocin(PG_FUNCTION_ARGS)
if (names == NIL) if (names == NIL)
PG_RETURN_NULL(); PG_RETURN_NULL();
clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true); clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true,
&fgc_flags);
if (clist == NULL) if (clist == NULL)
ereturn(escontext, (Datum) 0, ereturn(escontext, (Datum) 0,
@@ -164,13 +166,15 @@ regprocout(PG_FUNCTION_ARGS)
{ {
char *nspname; char *nspname;
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
/* /*
* Would this proc be found (uniquely!) by regprocin? If not, * Would this proc be found (uniquely!) by regprocin? If not,
* qualify it. * qualify it.
*/ */
clist = FuncnameGetCandidates(list_make1(makeString(proname)), clist = FuncnameGetCandidates(list_make1(makeString(proname)),
-1, NIL, false, false, false, false); -1, NIL, false, false, false, false,
&fgc_flags);
if (clist != NULL && clist->next == NULL && if (clist != NULL && clist->next == NULL &&
clist->oid == proid) clist->oid == proid)
nspname = NULL; nspname = NULL;
@@ -231,6 +235,7 @@ regprocedurein(PG_FUNCTION_ARGS)
int nargs; int nargs;
Oid argtypes[FUNC_MAX_ARGS]; Oid argtypes[FUNC_MAX_ARGS];
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
/* Handle "-" or numeric OID */ /* Handle "-" or numeric OID */
if (parseDashOrOid(pro_name_or_oid, &result, escontext)) if (parseDashOrOid(pro_name_or_oid, &result, escontext))
@@ -251,8 +256,8 @@ regprocedurein(PG_FUNCTION_ARGS)
escontext)) escontext))
PG_RETURN_NULL(); PG_RETURN_NULL();
clist = FuncnameGetCandidates(names, nargs, NIL, false, false, clist = FuncnameGetCandidates(names, nargs, NIL, false, false, false, true,
false, true); &fgc_flags);
for (; clist; clist = clist->next) for (; clist; clist = clist->next)
{ {
@@ -483,6 +488,7 @@ regoperin(PG_FUNCTION_ARGS)
Oid result; Oid result;
List *names; List *names;
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
/* Handle "0" or numeric OID */ /* Handle "0" or numeric OID */
if (parseNumericOid(opr_name_or_oid, &result, escontext)) if (parseNumericOid(opr_name_or_oid, &result, escontext))
@@ -502,7 +508,7 @@ regoperin(PG_FUNCTION_ARGS)
if (names == NIL) if (names == NIL)
PG_RETURN_NULL(); PG_RETURN_NULL();
clist = OpernameGetCandidates(names, '\0', true); clist = OpernameGetCandidates(names, '\0', true, &fgc_flags);
if (clist == NULL) if (clist == NULL)
ereturn(escontext, (Datum) 0, ereturn(escontext, (Datum) 0,
@@ -572,13 +578,14 @@ regoperout(PG_FUNCTION_ARGS)
else else
{ {
FuncCandidateList clist; FuncCandidateList clist;
int fgc_flags;
/* /*
* Would this oper be found (uniquely!) by regoperin? If not, * Would this oper be found (uniquely!) by regoperin? If not,
* qualify it. * qualify it.
*/ */
clist = OpernameGetCandidates(list_make1(makeString(oprname)), clist = OpernameGetCandidates(list_make1(makeString(oprname)),
'\0', false); '\0', false, &fgc_flags);
if (clist != NULL && clist->next == NULL && if (clist != NULL && clist->next == NULL &&
clist->oid == oprid) clist->oid == oprid)
result = pstrdup(oprname); result = pstrdup(oprname);

View File

@@ -13265,6 +13265,7 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
bool use_variadic; bool use_variadic;
char *nspname; char *nspname;
FuncDetailCode p_result; FuncDetailCode p_result;
int fgc_flags;
Oid p_funcid; Oid p_funcid;
Oid p_rettype; Oid p_rettype;
bool p_retset; bool p_retset;
@@ -13323,6 +13324,7 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
p_result = func_get_detail(list_make1(makeString(proname)), p_result = func_get_detail(list_make1(makeString(proname)),
NIL, argnames, nargs, argtypes, NIL, argnames, nargs, argtypes,
!use_variadic, true, false, !use_variadic, true, false,
&fgc_flags,
&p_funcid, &p_rettype, &p_funcid, &p_rettype,
&p_retset, &p_nvargs, &p_vatype, &p_retset, &p_nvargs, &p_vatype,
&p_true_typeids, NULL); &p_true_typeids, NULL);

View File

@@ -39,6 +39,24 @@ typedef struct _FuncCandidateList
Oid args[FLEXIBLE_ARRAY_MEMBER]; /* arg types */ Oid args[FLEXIBLE_ARRAY_MEMBER]; /* arg types */
} *FuncCandidateList; } *FuncCandidateList;
/*
* FuncnameGetCandidates also returns a bitmask containing these flags,
* which report on what it found or didn't find. They can help callers
* produce better error reports after a function lookup failure.
*/
#define FGC_SCHEMA_GIVEN 0x0001 /* Func name includes a schema */
#define FGC_SCHEMA_EXISTS 0x0002 /* Found the explicitly-specified schema */
#define FGC_NAME_EXISTS 0x0004 /* Found a routine by that name */
#define FGC_NAME_VISIBLE 0x0008 /* Found a routine name/schema match */
#define FGC_ARGCOUNT_MATCH 0x0010 /* Found a func with right # of args */
/* These bits relate only to calls using named or mixed arguments: */
#define FGC_ARGNAMES_MATCH 0x0020 /* Found a func matching all argnames */
#define FGC_ARGNAMES_NONDUP 0x0040 /* argnames don't overlap positional args */
#define FGC_ARGNAMES_ALL 0x0080 /* Found a func with no missing args */
#define FGC_ARGNAMES_VALID 0x0100 /* Found a fully-valid use of argnames */
/* These bits are actually filled by func_get_detail: */
#define FGC_VARIADIC_FAIL 0x0200 /* Disallowed VARIADIC with named args */
/* /*
* Result of checkTempNamespaceStatus * Result of checkTempNamespaceStatus
*/ */
@@ -102,12 +120,14 @@ extern FuncCandidateList FuncnameGetCandidates(List *names,
bool expand_variadic, bool expand_variadic,
bool expand_defaults, bool expand_defaults,
bool include_out_arguments, bool include_out_arguments,
bool missing_ok); bool missing_ok,
int *fgc_flags);
extern bool FunctionIsVisible(Oid funcid); extern bool FunctionIsVisible(Oid funcid);
extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright); extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind, extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind,
bool missing_schema_ok); bool missing_schema_ok,
int *fgc_flags);
extern bool OperatorIsVisible(Oid oprid); extern bool OperatorIsVisible(Oid oprid);
extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname); extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname);

View File

@@ -40,6 +40,7 @@ extern FuncDetailCode func_get_detail(List *funcname,
int nargs, Oid *argtypes, int nargs, Oid *argtypes,
bool expand_variadic, bool expand_defaults, bool expand_variadic, bool expand_defaults,
bool include_out_arguments, bool include_out_arguments,
int *fgc_flags,
Oid *funcid, Oid *rettype, Oid *funcid, Oid *rettype,
bool *retset, int *nvargs, Oid *vatype, bool *retset, int *nvargs, Oid *vatype,
Oid **true_typeids, List **argdefaults); Oid **true_typeids, List **argdefaults);

View File

@@ -41,7 +41,7 @@ select uses_global();
ERROR: function uses_global() does not exist ERROR: function uses_global() does not exist
LINE 1: select uses_global(); LINE 1: select uses_global();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no function of that name.
SET plperl.use_strict = false; SET plperl.use_strict = false;
create or replace function uses_global() returns text language plperl as $$ create or replace function uses_global() returns text language plperl as $$

View File

@@ -41,7 +41,7 @@ select uses_global();
ERROR: function uses_global() does not exist ERROR: function uses_global() does not exist
LINE 1: select uses_global(); LINE 1: select uses_global();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no function of that name.
SET plperl.use_strict = false; SET plperl.use_strict = false;
create or replace function uses_global() returns text language plperl as $$ create or replace function uses_global() returns text language plperl as $$

View File

@@ -440,7 +440,8 @@ $$;
ERROR: procedure test_proc12(integer, integer, text[]) does not exist ERROR: procedure test_proc12(integer, integer, text[]) does not exist
LINE 1: CALL test_proc12(_a, _b, _c) LINE 1: CALL test_proc12(_a, _b, _c)
^ ^
HINT: No procedure matches the given name and argument types. You might need to add explicit type casts. DETAIL: No procedure of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
QUERY: CALL test_proc12(_a, _b, _c) QUERY: CALL test_proc12(_a, _b, _c)
CONTEXT: PL/pgSQL function inline_code_block line 5 at CALL CONTEXT: PL/pgSQL function inline_code_block line 5 at CALL
-- transition variable assignment -- transition variable assignment

View File

@@ -466,7 +466,8 @@ select getf1(1);
ERROR: function getf1(integer) does not exist ERROR: function getf1(integer) does not exist
LINE 1: select getf1(1); LINE 1: select getf1(1);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select getf1(row(1,2)); select getf1(row(1,2));
getf1 getf1
------- -------

View File

@@ -63,7 +63,7 @@ SELECT exception_index_invalid_nested();
ERROR: spiexceptions.UndefinedFunction: function test5(unknown) does not exist ERROR: spiexceptions.UndefinedFunction: function test5(unknown) does not exist
LINE 1: SELECT test5('foo') LINE 1: SELECT test5('foo')
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no function of that name.
QUERY: SELECT test5('foo') QUERY: SELECT test5('foo')
CONTEXT: Traceback (most recent call last): CONTEXT: Traceback (most recent call last):
PL/Python function "exception_index_invalid_nested", line 1, in <module> PL/Python function "exception_index_invalid_nested", line 1, in <module>

View File

@@ -27,7 +27,7 @@ B 4 ParseComplete
B 4 BindComplete B 4 BindComplete
B 4 NoData B 4 NoData
B 15 CommandComplete "INSERT 0 1" B 15 CommandComplete "INSERT 0 1"
B NN ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" H "No function matches the given name and argument types. You might need to add explicit type casts." P "8" F "SSSS" L "SSSS" R "SSSS" \x00 B NN ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" D "There is no function of that name." P "8" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I B 5 ReadyForQuery I
B 4 ParseComplete B 4 ParseComplete
B 4 BindComplete B 4 BindComplete

View File

@@ -333,7 +333,7 @@ SELECT ext_cor_func();
ERROR: function ext_cor_func() does not exist ERROR: function ext_cor_func() does not exist
LINE 1: SELECT ext_cor_func(); LINE 1: SELECT ext_cor_func();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no function of that name.
SELECT * FROM ext_cor_view; SELECT * FROM ext_cor_view;
col col
------------------------ ------------------------
@@ -649,7 +649,6 @@ SELECT dep_req3b(); -- fails
ERROR: function public.dep_req2() does not exist ERROR: function public.dep_req2() does not exist
LINE 1: SELECT public.dep_req2() || ' req3b' LINE 1: SELECT public.dep_req2() || ' req3b'
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
QUERY: SELECT public.dep_req2() || ' req3b' QUERY: SELECT public.dep_req2() || ' req3b'
CONTEXT: SQL function "dep_req3b" statement 1 CONTEXT: SQL function "dep_req3b" statement 1
DROP EXTENSION test_ext_req_schema3; DROP EXTENSION test_ext_req_schema3;

View File

@@ -2041,7 +2041,8 @@ alter table anothertab alter column atcol1 drop default;
alter table anothertab alter column atcol1 type boolean alter table anothertab alter column atcol1 type boolean
using case when atcol1 % 2 = 0 then true else false end; -- fails using case when atcol1 % 2 = 0 then true else false end; -- fails
ERROR: operator does not exist: boolean <= integer ERROR: operator does not exist: boolean <= integer
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
alter table anothertab drop constraint anothertab_chk; alter table anothertab drop constraint anothertab_chk;
alter table anothertab drop constraint anothertab_chk; -- fails alter table anothertab drop constraint anothertab_chk; -- fails
ERROR: constraint "anothertab_chk" of relation "anothertab" does not exist ERROR: constraint "anothertab_chk" of relation "anothertab" does not exist

View File

@@ -2747,7 +2747,8 @@ SELECT width_bucket('5'::text, ARRAY[3, 4]::integer[]);
ERROR: function width_bucket(text, integer[]) does not exist ERROR: function width_bucket(text, integer[]) does not exist
LINE 1: SELECT width_bucket('5'::text, ARRAY[3, 4]::integer[]); LINE 1: SELECT width_bucket('5'::text, ARRAY[3, 4]::integer[]);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
SELECT width_bucket(5, ARRAY[3, 4, NULL]); SELECT width_bucket(5, ARRAY[3, 4, NULL]);
ERROR: thresholds array must not contain NULLs ERROR: thresholds array must not contain NULLs
SELECT width_bucket(5, ARRAY[ARRAY[1, 2], ARRAY[3, 4]]); SELECT width_bucket(5, ARRAY[ARRAY[1, 2], ARRAY[3, 4]]);

View File

@@ -28,14 +28,16 @@ SELECT casttestfunc('foo'::text); -- fails, as there's no cast
ERROR: function casttestfunc(text) does not exist ERROR: function casttestfunc(text) does not exist
LINE 1: SELECT casttestfunc('foo'::text); LINE 1: SELECT casttestfunc('foo'::text);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- Try binary coercion cast -- Try binary coercion cast
CREATE CAST (text AS casttesttype) WITHOUT FUNCTION; CREATE CAST (text AS casttesttype) WITHOUT FUNCTION;
SELECT casttestfunc('foo'::text); -- doesn't work, as the cast is explicit SELECT casttestfunc('foo'::text); -- doesn't work, as the cast is explicit
ERROR: function casttestfunc(text) does not exist ERROR: function casttestfunc(text) does not exist
LINE 1: SELECT casttestfunc('foo'::text); LINE 1: SELECT casttestfunc('foo'::text);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
SELECT casttestfunc('foo'::text::casttesttype); -- should work SELECT casttestfunc('foo'::text::casttesttype); -- should work
casttestfunc casttestfunc
-------------- --------------

View File

@@ -304,7 +304,8 @@ CREATE FUNCTION functest_S_xx(x date) RETURNS boolean
ERROR: operator does not exist: date > integer ERROR: operator does not exist: date > integer
LINE 3: RETURN x > 1; LINE 3: RETURN x > 1;
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- tricky parsing -- tricky parsing
CREATE FUNCTION functest_S_15(x int) RETURNS boolean CREATE FUNCTION functest_S_15(x int) RETURNS boolean
LANGUAGE SQL LANGUAGE SQL

View File

@@ -24,6 +24,25 @@ SELECT @#@ 24;
620448401733239439360000 620448401733239439360000
(1 row) (1 row)
-- Test error cases
select @@##@@ 24; -- no such operator
ERROR: operator does not exist: @@##@@ integer
LINE 1: select @@##@@ 24;
^
DETAIL: There is no operator of that name.
set search_path = pg_catalog;
select @#@ 24; -- wrong schema
ERROR: operator does not exist: @#@ integer
LINE 1: select @#@ 24;
^
DETAIL: An operator of that name exists, but it is not in the search_path.
reset search_path;
select @#@ 24.0; -- wrong data type
ERROR: operator does not exist: @#@ numeric
LINE 1: select @#@ 24.0;
^
DETAIL: No operator of that name accepts the given argument type.
HINT: You might need to add an explicit type cast.
-- Test comments -- Test comments
COMMENT ON OPERATOR ###### (NONE, int4) IS 'bad prefix'; COMMENT ON OPERATOR ###### (NONE, int4) IS 'bad prefix';
ERROR: operator does not exist: ###### integer ERROR: operator does not exist: ###### integer

View File

@@ -2,7 +2,7 @@ CALL nonexistent(); -- error
ERROR: procedure nonexistent() does not exist ERROR: procedure nonexistent() does not exist
LINE 1: CALL nonexistent(); LINE 1: CALL nonexistent();
^ ^
HINT: No procedure matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no procedure of that name.
CALL random(); -- error CALL random(); -- error
ERROR: random() is not a procedure ERROR: random() is not a procedure
LINE 1: CALL random(); LINE 1: CALL random();
@@ -299,7 +299,8 @@ CALL ptest9(1./0.); -- error
ERROR: procedure ptest9(numeric) does not exist ERROR: procedure ptest9(numeric) does not exist
LINE 1: CALL ptest9(1./0.); LINE 1: CALL ptest9(1./0.);
^ ^
HINT: No procedure matches the given name and argument types. You might need to add explicit type casts. DETAIL: No procedure of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- check named-parameter matching -- check named-parameter matching
CREATE PROCEDURE ptest10(OUT a int, IN b int, IN c int) CREATE PROCEDURE ptest10(OUT a int, IN b int, IN c int)
LANGUAGE SQL AS $$ SELECT b - c $$; LANGUAGE SQL AS $$ SELECT b - c $$;

View File

@@ -1924,7 +1924,8 @@ select 'foo'::text = any((select array['abc','def','foo']::text[])); -- fail
ERROR: operator does not exist: text = text[] ERROR: operator does not exist: text = text[]
LINE 1: select 'foo'::text = any((select array['abc','def','foo']::t... LINE 1: select 'foo'::text = any((select array['abc','def','foo']::t...
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select 'foo'::text = any((select array['abc','def','foo']::text[])::text[]); select 'foo'::text = any((select array['abc','def','foo']::text[])::text[]);
?column? ?column?
---------- ----------

View File

@@ -415,7 +415,8 @@ select row(0,1)::dcomptype; -- fail
ERROR: value for domain dcomptype violates check constraint "c1" ERROR: value for domain dcomptype violates check constraint "c1"
alter type comptype alter attribute r type varchar; -- fail alter type comptype alter attribute r type varchar; -- fail
ERROR: operator does not exist: character varying > double precision ERROR: operator does not exist: character varying > double precision
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
alter type comptype alter attribute r type bigint; alter type comptype alter attribute r type bigint;
alter type comptype drop attribute r; -- fail alter type comptype drop attribute r; -- fail
ERROR: cannot drop column r of composite type comptype because other objects depend on it ERROR: cannot drop column r of composite type comptype because other objects depend on it

View File

@@ -218,7 +218,8 @@ select '(0,0)'::point in ('(0,0,0,0)'::box, point(0,0));
ERROR: operator does not exist: point = box ERROR: operator does not exist: point = box
LINE 1: select '(0,0)'::point in ('(0,0,0,0)'::box, point(0,0)); LINE 1: select '(0,0)'::point in ('(0,0,0,0)'::box, point(0,0));
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- --
-- Tests for ScalarArrayOpExpr with a hashfn -- Tests for ScalarArrayOpExpr with a hashfn
-- --

View File

@@ -1777,7 +1777,8 @@ SELECT p.f1, l.s, l.s # p.f1 AS intersection
ERROR: operator does not exist: lseg # point ERROR: operator does not exist: lseg # point
LINE 1: SELECT p.f1, l.s, l.s # p.f1 AS intersection LINE 1: SELECT p.f1, l.s, l.s # p.f1 AS intersection
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- Length -- Length
SELECT s, @-@ s FROM LSEG_TBL; SELECT s, @-@ s FROM LSEG_TBL;
s | ?column? s | ?column?

View File

@@ -605,7 +605,8 @@ SELECT date '1991-02-03' - time with time zone '04:05:06 UTC' AS "Subtract Time
ERROR: operator does not exist: date - time with time zone ERROR: operator does not exist: date - time with time zone
LINE 1: SELECT date '1991-02-03' - time with time zone '04:05:06 UTC... LINE 1: SELECT date '1991-02-03' - time with time zone '04:05:06 UTC...
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- --
-- timestamp, interval arithmetic -- timestamp, interval arithmetic
-- --

View File

@@ -171,12 +171,12 @@ SELECT num_nonnulls();
ERROR: function num_nonnulls() does not exist ERROR: function num_nonnulls() does not exist
LINE 1: SELECT num_nonnulls(); LINE 1: SELECT num_nonnulls();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given number of arguments.
SELECT num_nulls(); SELECT num_nulls();
ERROR: function num_nulls() does not exist ERROR: function num_nulls() does not exist
LINE 1: SELECT num_nulls(); LINE 1: SELECT num_nulls();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given number of arguments.
-- --
-- canonicalize_path() -- canonicalize_path()
-- --

View File

@@ -3096,7 +3096,8 @@ select multirange_of_text(textrange2('a','Z')); -- should fail
ERROR: function multirange_of_text(textrange2) does not exist ERROR: function multirange_of_text(textrange2) does not exist
LINE 1: select multirange_of_text(textrange2('a','Z')); LINE 1: select multirange_of_text(textrange2('a','Z'));
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select multirange_of_text(textrange1('a','Z')) @> 'b'::text; select multirange_of_text(textrange1('a','Z')) @> 'b'::text;
ERROR: range lower bound must be less than or equal to range upper bound ERROR: range lower bound must be less than or equal to range upper bound
select unnest(multirange_of_text(textrange1('a','b'), textrange1('d','e'))); select unnest(multirange_of_text(textrange1('a','b'), textrange1('d','e')));
@@ -3160,7 +3161,8 @@ select anyarray_anymultirange_func(ARRAY[1,2], nummultirange(numrange(10,20)));
ERROR: function anyarray_anymultirange_func(integer[], nummultirange) does not exist ERROR: function anyarray_anymultirange_func(integer[], nummultirange) does not exist
LINE 1: select anyarray_anymultirange_func(ARRAY[1,2], nummultirange... LINE 1: select anyarray_anymultirange_func(ARRAY[1,2], nummultirange...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyarray_anymultirange_func(anyarray, anymultirange); drop function anyarray_anymultirange_func(anyarray, anymultirange);
-- should fail -- should fail
create function bogus_func(anyelement) create function bogus_func(anyelement)
@@ -3199,7 +3201,8 @@ select multirangetypes_sql(nummultirange(numrange(1,10)), ARRAY[2,20]); -- matc
ERROR: function multirangetypes_sql(nummultirange, integer[]) does not exist ERROR: function multirangetypes_sql(nummultirange, integer[]) does not exist
LINE 1: select multirangetypes_sql(nummultirange(numrange(1,10)), AR... LINE 1: select multirangetypes_sql(nummultirange(numrange(1,10)), AR...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
create function anycompatiblearray_anycompatiblemultirange_func(a anycompatiblearray, mr anycompatiblemultirange) create function anycompatiblearray_anycompatiblemultirange_func(a anycompatiblearray, mr anycompatiblemultirange)
returns anycompatible as 'select $1[1] + lower($2);' language sql; returns anycompatible as 'select $1[1] + lower($2);' language sql;
select anycompatiblearray_anycompatiblemultirange_func(ARRAY[1,2], multirange(int4range(10,20))); select anycompatiblearray_anycompatiblemultirange_func(ARRAY[1,2], multirange(int4range(10,20)));
@@ -3219,7 +3222,8 @@ select anycompatiblearray_anycompatiblemultirange_func(ARRAY[1.1,2], multirange(
ERROR: function anycompatiblearray_anycompatiblemultirange_func(numeric[], int4multirange) does not exist ERROR: function anycompatiblearray_anycompatiblemultirange_func(numeric[], int4multirange) does not exist
LINE 1: select anycompatiblearray_anycompatiblemultirange_func(ARRAY... LINE 1: select anycompatiblearray_anycompatiblemultirange_func(ARRAY...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anycompatiblearray_anycompatiblemultirange_func(anycompatiblearray, anycompatiblemultirange); drop function anycompatiblearray_anycompatiblemultirange_func(anycompatiblearray, anycompatiblemultirange);
create function anycompatiblerange_anycompatiblemultirange_func(r anycompatiblerange, mr anycompatiblemultirange) create function anycompatiblerange_anycompatiblemultirange_func(r anycompatiblerange, mr anycompatiblemultirange)
returns anycompatible as 'select lower($1) + lower($2);' language sql; returns anycompatible as 'select lower($1) + lower($2);' language sql;
@@ -3234,7 +3238,8 @@ select anycompatiblerange_anycompatiblemultirange_func(numrange(1,2), multirange
ERROR: function anycompatiblerange_anycompatiblemultirange_func(numrange, int4multirange) does not exist ERROR: function anycompatiblerange_anycompatiblemultirange_func(numrange, int4multirange) does not exist
LINE 1: select anycompatiblerange_anycompatiblemultirange_func(numra... LINE 1: select anycompatiblerange_anycompatiblemultirange_func(numra...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anycompatiblerange_anycompatiblemultirange_func(anycompatiblerange, anycompatiblemultirange); drop function anycompatiblerange_anycompatiblemultirange_func(anycompatiblerange, anycompatiblemultirange);
-- should fail -- should fail
create function bogus_func(anycompatible) create function bogus_func(anycompatible)

View File

@@ -1763,7 +1763,8 @@ select f1(point(3,4)); -- fail for lack of + operator
ERROR: operator does not exist: point + integer ERROR: operator does not exist: point + integer
LINE 1: x + 1 LINE 1: x + 1
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
QUERY: x + 1 QUERY: x + 1
CONTEXT: PL/pgSQL function f1(anyelement) line 3 at RETURN CONTEXT: PL/pgSQL function f1(anyelement) line 3 at RETURN
drop function f1(x anyelement); drop function f1(x anyelement);
@@ -1848,7 +1849,8 @@ select f1(int4range(42, 49), 11, 4.5) as fail; -- range type doesn't fit
ERROR: function f1(int4range, integer, numeric) does not exist ERROR: function f1(int4range, integer, numeric) does not exist
LINE 1: select f1(int4range(42, 49), 11, 4.5) as fail; LINE 1: select f1(int4range(42, 49), 11, 4.5) as fail;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function f1(x anycompatiblerange, y anycompatible, z anycompatible); drop function f1(x anycompatiblerange, y anycompatible, z anycompatible);
-- fail, can't infer type: -- fail, can't infer type:
create function f1(x anycompatible) returns anycompatiblerange as $$ create function f1(x anycompatible) returns anycompatiblerange as $$
@@ -1902,7 +1904,8 @@ select x, pg_typeof(x), y, pg_typeof(y)
ERROR: function f1(integer, numeric[], integer, numeric) does not exist ERROR: function f1(integer, numeric[], integer, numeric) does not exist
LINE 2: from f1(11, array[1, 2.2], 42, 34.5); LINE 2: from f1(11, array[1, 2.2], 42, 34.5);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function f1(a anyelement, b anyarray, drop function f1(a anyelement, b anyarray,
c anycompatible, d anycompatible); c anycompatible, d anycompatible);
-- --
@@ -3072,7 +3075,7 @@ select shadowtest(1);
ERROR: function shadowtest(integer) does not exist ERROR: function shadowtest(integer) does not exist
LINE 1: select shadowtest(1); LINE 1: select shadowtest(1);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no function of that name.
reset plpgsql.extra_errors; reset plpgsql.extra_errors;
reset plpgsql.extra_warnings; reset plpgsql.extra_warnings;
create or replace function shadowtest(f1 int) create or replace function shadowtest(f1 int)

View File

@@ -15,7 +15,8 @@ select polyf(point(3,4)); -- fail for lack of + operator
ERROR: operator does not exist: point + integer ERROR: operator does not exist: point + integer
LINE 2: select x + 1 LINE 2: select x + 1
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
QUERY: QUERY:
select x + 1 select x + 1
@@ -95,7 +96,8 @@ select polyf(int4range(42, 49), 11, 4.5) as fail; -- range type doesn't fit
ERROR: function polyf(int4range, integer, numeric) does not exist ERROR: function polyf(int4range, integer, numeric) does not exist
LINE 1: select polyf(int4range(42, 49), 11, 4.5) as fail; LINE 1: select polyf(int4range(42, 49), 11, 4.5) as fail;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function polyf(x anycompatiblerange, y anycompatible, z anycompatible); drop function polyf(x anycompatiblerange, y anycompatible, z anycompatible);
create function polyf(x anycompatiblemultirange, y anycompatible, z anycompatible) returns anycompatiblearray as $$ create function polyf(x anycompatiblemultirange, y anycompatible, z anycompatible) returns anycompatiblearray as $$
select array[lower(x), upper(x), y, z] select array[lower(x), upper(x), y, z]
@@ -110,7 +112,8 @@ select polyf(multirange(int4range(42, 49)), 11, 4.5) as fail; -- range type doe
ERROR: function polyf(int4multirange, integer, numeric) does not exist ERROR: function polyf(int4multirange, integer, numeric) does not exist
LINE 1: select polyf(multirange(int4range(42, 49)), 11, 4.5) as fail... LINE 1: select polyf(multirange(int4range(42, 49)), 11, 4.5) as fail...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function polyf(x anycompatiblemultirange, y anycompatible, z anycompatible); drop function polyf(x anycompatiblemultirange, y anycompatible, z anycompatible);
-- fail, can't infer type: -- fail, can't infer type:
create function polyf(x anycompatible) returns anycompatiblerange as $$ create function polyf(x anycompatible) returns anycompatiblerange as $$
@@ -176,7 +179,8 @@ select x, pg_typeof(x), y, pg_typeof(y)
ERROR: function polyf(integer, numeric[], integer, numeric) does not exist ERROR: function polyf(integer, numeric[], integer, numeric) does not exist
LINE 2: from polyf(11, array[1, 2.2], 42, 34.5); LINE 2: from polyf(11, array[1, 2.2], 42, 34.5);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function polyf(a anyelement, b anyarray, drop function polyf(a anyelement, b anyarray,
c anycompatible, d anycompatible); c anycompatible, d anycompatible);
create function polyf(anyrange) returns anymultirange create function polyf(anyrange) returns anymultirange
@@ -990,7 +994,7 @@ select myleast(); -- fail
ERROR: function myleast() does not exist ERROR: function myleast() does not exist
LINE 1: select myleast(); LINE 1: select myleast();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given number of arguments.
-- test with variadic call parameter -- test with variadic call parameter
select myleast(variadic array[1,2,3,4,-1]); select myleast(variadic array[1,2,3,4,-1]);
myleast myleast
@@ -1060,17 +1064,20 @@ select formarray(1.1, array[1.2,55.5]); -- fail without variadic
ERROR: function formarray(numeric, numeric[]) does not exist ERROR: function formarray(numeric, numeric[]) does not exist
LINE 1: select formarray(1.1, array[1.2,55.5]); LINE 1: select formarray(1.1, array[1.2,55.5]);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select formarray(1, 'x'::text); -- fail, type mismatch select formarray(1, 'x'::text); -- fail, type mismatch
ERROR: function formarray(integer, text) does not exist ERROR: function formarray(integer, text) does not exist
LINE 1: select formarray(1, 'x'::text); LINE 1: select formarray(1, 'x'::text);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select formarray(1, variadic array['x'::text]); -- fail, type mismatch select formarray(1, variadic array['x'::text]); -- fail, type mismatch
ERROR: function formarray(integer, text[]) does not exist ERROR: function formarray(integer, text[]) does not exist
LINE 1: select formarray(1, variadic array['x'::text]); LINE 1: select formarray(1, variadic array['x'::text]);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function formarray(anyelement, variadic anyarray); drop function formarray(anyelement, variadic anyarray);
-- test pg_typeof() function -- test pg_typeof() function
select pg_typeof(null); -- unknown select pg_typeof(null); -- unknown
@@ -1154,7 +1161,7 @@ select dfunc(10, 20, 30); -- fail
ERROR: function dfunc(integer, integer, integer) does not exist ERROR: function dfunc(integer, integer, integer) does not exist
LINE 1: select dfunc(10, 20, 30); LINE 1: select dfunc(10, 20, 30);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given number of arguments.
drop function dfunc(); -- fail drop function dfunc(); -- fail
ERROR: function dfunc() does not exist ERROR: function dfunc() does not exist
drop function dfunc(int); -- fail drop function dfunc(int); -- fail
@@ -1203,7 +1210,8 @@ select dfunc(); -- fail: which dfunc should be called? int or text
ERROR: function dfunc() is not unique ERROR: function dfunc() is not unique
LINE 1: select dfunc(); LINE 1: select dfunc();
^ ^
HINT: Could not choose a best candidate function. You might need to add explicit type casts. DETAIL: Could not choose a best candidate function.
HINT: You might need to add explicit type casts.
select dfunc('Hi'); -- ok select dfunc('Hi'); -- ok
dfunc dfunc
----------- -----------
@@ -1242,17 +1250,20 @@ select dfunc(); -- fail
ERROR: function dfunc() is not unique ERROR: function dfunc() is not unique
LINE 1: select dfunc(); LINE 1: select dfunc();
^ ^
HINT: Could not choose a best candidate function. You might need to add explicit type casts. DETAIL: Could not choose a best candidate function.
HINT: You might need to add explicit type casts.
select dfunc(1); -- fail select dfunc(1); -- fail
ERROR: function dfunc(integer) is not unique ERROR: function dfunc(integer) is not unique
LINE 1: select dfunc(1); LINE 1: select dfunc(1);
^ ^
HINT: Could not choose a best candidate function. You might need to add explicit type casts. DETAIL: Could not choose a best candidate function.
HINT: You might need to add explicit type casts.
select dfunc(1, 2); -- fail select dfunc(1, 2); -- fail
ERROR: function dfunc(integer, integer) is not unique ERROR: function dfunc(integer, integer) is not unique
LINE 1: select dfunc(1, 2); LINE 1: select dfunc(1, 2);
^ ^
HINT: Could not choose a best candidate function. You might need to add explicit type casts. DETAIL: Could not choose a best candidate function.
HINT: You might need to add explicit type casts.
select dfunc(1, 2, 3); -- ok select dfunc(1, 2, 3); -- ok
dfunc dfunc
------- -------
@@ -1310,7 +1321,7 @@ select dfunc(); -- fail
ERROR: function dfunc() does not exist ERROR: function dfunc() does not exist
LINE 1: select dfunc(); LINE 1: select dfunc();
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given number of arguments.
select dfunc(10); select dfunc(10);
dfunc dfunc
------- -------
@@ -1371,7 +1382,8 @@ select dfunc(1); -- fail
ERROR: function dfunc(integer) is not unique ERROR: function dfunc(integer) is not unique
LINE 1: select dfunc(1); LINE 1: select dfunc(1);
^ ^
HINT: Could not choose a best candidate function. You might need to add explicit type casts. DETAIL: Could not choose a best candidate function.
HINT: You might need to add explicit type casts.
-- but this works since the ambiguous functions aren't preferred anyway -- but this works since the ambiguous functions aren't preferred anyway
select dfunc('Hi'); select dfunc('Hi');
dfunc dfunc
@@ -1417,7 +1429,7 @@ select * from dfunc(0); -- fail
ERROR: function dfunc(integer) does not exist ERROR: function dfunc(integer) does not exist
LINE 1: select * from dfunc(0); LINE 1: select * from dfunc(0);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given number of arguments.
select * from dfunc(1,2); select * from dfunc(1,2);
a | b | c | d a | b | c | d
---+---+---+--- ---+---+---+---
@@ -1448,18 +1460,72 @@ select * from dfunc(x := 10, b := 20, c := 30); -- fail, unknown param
ERROR: function dfunc(x => integer, b => integer, c => integer) does not exist ERROR: function dfunc(x => integer, b => integer, c => integer) does not exist
LINE 1: select * from dfunc(x := 10, b := 20, c := 30); LINE 1: select * from dfunc(x := 10, b := 20, c := 30);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument names.
select * from dfunc(10, 10, a := 20); -- fail, a overlaps positional parameter select * from dfunc(10, 10, a := 20); -- fail, a overlaps positional parameter
ERROR: function dfunc(integer, integer, a => integer) does not exist ERROR: function dfunc(integer, integer, a => integer) does not exist
LINE 1: select * from dfunc(10, 10, a := 20); LINE 1: select * from dfunc(10, 10, a := 20);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: In the closest available match, an argument was specified both positionally and by name.
select * from dfunc(1,c := 2,d := 3); -- fail, no value for b select * from dfunc(1,c := 2,d := 3); -- fail, no value for b
ERROR: function dfunc(integer, c => integer, d => integer) does not exist ERROR: function dfunc(integer, c => integer, d => integer) does not exist
LINE 1: select * from dfunc(1,c := 2,d := 3); LINE 1: select * from dfunc(1,c := 2,d := 3);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: In the closest available match, not all required arguments were supplied.
drop function dfunc(int, int, int, int); drop function dfunc(int, int, int, int);
create function xleast(x numeric, variadic arr numeric[])
returns numeric as $$
select least(x, min(arr[i])) from generate_subscripts(arr, 1) g(i);
$$ language sql;
select xleast(x => 1, variadic arr => array[2,3]);
xleast
--------
1
(1 row)
select xleast(1, variadic arr => array[2,3]);
xleast
--------
1
(1 row)
set search_path = pg_catalog;
select xleast(1, variadic arr => array[2,3]); -- wrong schema
ERROR: function xleast(integer, arr => integer[]) does not exist
LINE 1: select xleast(1, variadic arr => array[2,3]);
^
DETAIL: A function of that name exists, but it is not in the search_path.
reset search_path;
select xleast(foo => 1, variadic arr => array[2,3]); -- wrong argument name
ERROR: function xleast(foo => integer, arr => integer[]) does not exist
LINE 1: select xleast(foo => 1, variadic arr => array[2,3]);
^
DETAIL: No function of that name accepts the given argument names.
select xleast(x => 1, variadic array[2,3]); -- misuse of mixed notation
ERROR: positional argument cannot follow named argument
LINE 1: select xleast(x => 1, variadic array[2,3]);
^
select xleast(1, variadic x => array[2,3]); -- misuse of mixed notation
ERROR: function xleast(integer, x => integer[]) does not exist
LINE 1: select xleast(1, variadic x => array[2,3]);
^
DETAIL: In the closest available match, an argument was specified both positionally and by name.
select xleast(arr => array[1], variadic x => 3); -- wrong arg is VARIADIC
ERROR: function xleast(arr => integer[], x => integer) does not exist
LINE 1: select xleast(arr => array[1], variadic x => 3);
^
HINT: The VARIADIC parameter must be placed last, even when using argument names.
select xleast(arr => array[1], x => 3); -- failed to use VARIADIC
ERROR: function xleast(arr => integer[], x => integer) does not exist
LINE 1: select xleast(arr => array[1], x => 3);
^
HINT: This call would be correct if the variadic array were labeled VARIADIC and placed last.
select xleast(arr => 1, variadic x => array[2,3]); -- mixed-up args
ERROR: function xleast(arr => integer, x => integer[]) does not exist
LINE 1: select xleast(arr => 1, variadic x => array[2,3]);
^
DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function xleast(x numeric, variadic arr numeric[]);
-- test with different parameter types -- test with different parameter types
create function dfunc(a varchar, b numeric, c date = current_date) create function dfunc(a varchar, b numeric, c date = current_date)
returns table (a varchar, b numeric, c date) as $$ returns table (a varchar, b numeric, c date) as $$
@@ -1499,7 +1565,8 @@ select * from dfunc('Hello World', c := 20, b := '2009-07-25'::date); -- fail
ERROR: function dfunc(unknown, c => integer, b => date) does not exist ERROR: function dfunc(unknown, c => integer, b => date) does not exist
LINE 1: select * from dfunc('Hello World', c := 20, b := '2009-07-25... LINE 1: select * from dfunc('Hello World', c := 20, b := '2009-07-25...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function dfunc(varchar, numeric, date); drop function dfunc(varchar, numeric, date);
-- test out parameters with named params -- test out parameters with named params
create function dfunc(a varchar = 'def a', out _a varchar, c numeric = NULL, out _c numeric) create function dfunc(a varchar = 'def a', out _a varchar, c numeric = NULL, out _c numeric)
@@ -1844,7 +1911,8 @@ select x, pg_typeof(x) from anyctest(11, point(1,2)) x; -- fail
ERROR: function anyctest(integer, point) does not exist ERROR: function anyctest(integer, point) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, point(1,2)) x; LINE 1: select x, pg_typeof(x) from anyctest(11, point(1,2)) x;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select x, pg_typeof(x) from anyctest('11', '12.3') x; -- defaults to text select x, pg_typeof(x) from anyctest('11', '12.3') x; -- defaults to text
x | pg_typeof x | pg_typeof
------+----------- ------+-----------
@@ -1872,7 +1940,8 @@ select x, pg_typeof(x) from anyctest(11, array[1,2]) x; -- fail
ERROR: function anyctest(integer, integer[]) does not exist ERROR: function anyctest(integer, integer[]) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, array[1,2]) x; LINE 1: select x, pg_typeof(x) from anyctest(11, array[1,2]) x;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyctest(anycompatible, anycompatible); drop function anyctest(anycompatible, anycompatible);
create function anyctest(anycompatible, anycompatiblearray) create function anyctest(anycompatible, anycompatiblearray)
returns anycompatiblearray as $$ returns anycompatiblearray as $$
@@ -1906,12 +1975,14 @@ select x, pg_typeof(x) from anyctest(11, array[point(1,2)]) x; -- fail
ERROR: function anyctest(integer, point[]) does not exist ERROR: function anyctest(integer, point[]) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, array[point(1,2)]) ... LINE 1: select x, pg_typeof(x) from anyctest(11, array[point(1,2)]) ...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select x, pg_typeof(x) from anyctest(11, 12) x; -- fail select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
ERROR: function anyctest(integer, integer) does not exist ERROR: function anyctest(integer, integer) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x; LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyctest(anycompatible, anycompatiblearray); drop function anyctest(anycompatible, anycompatiblearray);
create function anyctest(anycompatible, anycompatiblerange) create function anyctest(anycompatible, anycompatiblerange)
returns anycompatiblerange as $$ returns anycompatiblerange as $$
@@ -1933,12 +2004,14 @@ select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
ERROR: function anyctest(integer, integer) does not exist ERROR: function anyctest(integer, integer) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x; LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x; -- fail select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x; -- fail
ERROR: function anyctest(numeric, int4range) does not exist ERROR: function anyctest(numeric, int4range) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x... LINE 1: select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select x, pg_typeof(x) from anyctest(11.2, '[4,7)') x; -- fail select x, pg_typeof(x) from anyctest(11.2, '[4,7)') x; -- fail
ERROR: could not determine polymorphic type anycompatiblerange because input has type unknown ERROR: could not determine polymorphic type anycompatiblerange because input has type unknown
drop function anyctest(anycompatible, anycompatiblerange); drop function anyctest(anycompatible, anycompatiblerange);
@@ -1956,7 +2029,8 @@ select x, pg_typeof(x) from anyctest(int4range(11,12), numrange(4,7)) x; -- fail
ERROR: function anyctest(int4range, numrange) does not exist ERROR: function anyctest(int4range, numrange) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(int4range(11,12), numra... LINE 1: select x, pg_typeof(x) from anyctest(int4range(11,12), numra...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyctest(anycompatiblerange, anycompatiblerange); drop function anyctest(anycompatiblerange, anycompatiblerange);
-- fail, can't infer result type: -- fail, can't infer result type:
create function anyctest(anycompatible) create function anyctest(anycompatible)
@@ -1985,12 +2059,14 @@ select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
ERROR: function anyctest(integer, integer) does not exist ERROR: function anyctest(integer, integer) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x; LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select x, pg_typeof(x) from anyctest(11.2, multirange(int4range(4,7))) x; -- fail select x, pg_typeof(x) from anyctest(11.2, multirange(int4range(4,7))) x; -- fail
ERROR: function anyctest(numeric, int4multirange) does not exist ERROR: function anyctest(numeric, int4multirange) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11.2, multirange(int4ra... LINE 1: select x, pg_typeof(x) from anyctest(11.2, multirange(int4ra...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select x, pg_typeof(x) from anyctest(11.2, '{[4,7)}') x; -- fail select x, pg_typeof(x) from anyctest(11.2, '{[4,7)}') x; -- fail
ERROR: could not determine polymorphic type anycompatiblemultirange because input has type unknown ERROR: could not determine polymorphic type anycompatiblemultirange because input has type unknown
drop function anyctest(anycompatible, anycompatiblemultirange); drop function anyctest(anycompatible, anycompatiblemultirange);
@@ -2008,7 +2084,8 @@ select x, pg_typeof(x) from anyctest(multirange(int4range(11,12)), multirange(nu
ERROR: function anyctest(int4multirange, nummultirange) does not exist ERROR: function anyctest(int4multirange, nummultirange) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(multirange(int4range(11... LINE 1: select x, pg_typeof(x) from anyctest(multirange(int4range(11...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyctest(anycompatiblemultirange, anycompatiblemultirange); drop function anyctest(anycompatiblemultirange, anycompatiblemultirange);
-- fail, can't infer result type: -- fail, can't infer result type:
create function anyctest(anycompatible) create function anyctest(anycompatible)
@@ -2037,7 +2114,8 @@ select x, pg_typeof(x) from anyctest(array[11], array[1,2]) x; -- fail
ERROR: function anyctest(integer[], integer[]) does not exist ERROR: function anyctest(integer[], integer[]) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(array[11], array[1,2]) ... LINE 1: select x, pg_typeof(x) from anyctest(array[11], array[1,2]) ...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyctest(anycompatiblenonarray, anycompatiblenonarray); drop function anyctest(anycompatiblenonarray, anycompatiblenonarray);
create function anyctest(a anyelement, b anyarray, create function anyctest(a anyelement, b anyarray,
c anycompatible, d anycompatible) c anycompatible, d anycompatible)
@@ -2066,7 +2144,8 @@ select x, pg_typeof(x) from anyctest(11, array[1, 2.2], 42, 34.5) x; -- fail
ERROR: function anyctest(integer, numeric[], integer, numeric) does not exist ERROR: function anyctest(integer, numeric[], integer, numeric) does not exist
LINE 1: select x, pg_typeof(x) from anyctest(11, array[1, 2.2], 42, ... LINE 1: select x, pg_typeof(x) from anyctest(11, array[1, 2.2], 42, ...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyctest(a anyelement, b anyarray, drop function anyctest(a anyelement, b anyarray,
c anycompatible, d anycompatible); c anycompatible, d anycompatible);
create function anyctest(variadic anycompatiblearray) create function anyctest(variadic anycompatiblearray)

View File

@@ -1630,7 +1630,8 @@ select anyarray_anyrange_func(ARRAY[1,2], numrange(10,20));
ERROR: function anyarray_anyrange_func(integer[], numrange) does not exist ERROR: function anyarray_anyrange_func(integer[], numrange) does not exist
LINE 1: select anyarray_anyrange_func(ARRAY[1,2], numrange(10,20)); LINE 1: select anyarray_anyrange_func(ARRAY[1,2], numrange(10,20));
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anyarray_anyrange_func(anyarray, anyrange); drop function anyarray_anyrange_func(anyarray, anyrange);
-- should fail -- should fail
create function bogus_func(anyelement) create function bogus_func(anyelement)
@@ -1669,7 +1670,8 @@ select rangetypes_sql(numrange(1,10), ARRAY[2,20]); -- match failure
ERROR: function rangetypes_sql(numrange, integer[]) does not exist ERROR: function rangetypes_sql(numrange, integer[]) does not exist
LINE 1: select rangetypes_sql(numrange(1,10), ARRAY[2,20]); LINE 1: select rangetypes_sql(numrange(1,10), ARRAY[2,20]);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
create function anycompatiblearray_anycompatiblerange_func(a anycompatiblearray, r anycompatiblerange) create function anycompatiblearray_anycompatiblerange_func(a anycompatiblearray, r anycompatiblerange)
returns anycompatible as 'select $1[1] + lower($2);' language sql; returns anycompatible as 'select $1[1] + lower($2);' language sql;
select anycompatiblearray_anycompatiblerange_func(ARRAY[1,2], int4range(10,20)); select anycompatiblearray_anycompatiblerange_func(ARRAY[1,2], int4range(10,20));
@@ -1689,7 +1691,8 @@ select anycompatiblearray_anycompatiblerange_func(ARRAY[1.1,2], int4range(10,20)
ERROR: function anycompatiblearray_anycompatiblerange_func(numeric[], int4range) does not exist ERROR: function anycompatiblearray_anycompatiblerange_func(numeric[], int4range) does not exist
LINE 1: select anycompatiblearray_anycompatiblerange_func(ARRAY[1.1,... LINE 1: select anycompatiblearray_anycompatiblerange_func(ARRAY[1.1,...
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
drop function anycompatiblearray_anycompatiblerange_func(anycompatiblearray, anycompatiblerange); drop function anycompatiblearray_anycompatiblerange_func(anycompatiblearray, anycompatiblerange);
-- should fail -- should fail
create function bogus_func(anycompatible) create function bogus_func(anycompatible)

View File

@@ -965,7 +965,8 @@ select text(fullname) from fullname; -- error
ERROR: function text(fullname) does not exist ERROR: function text(fullname) does not exist
LINE 1: select text(fullname) from fullname; LINE 1: select text(fullname) from fullname;
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select fullname.text from fullname; -- error select fullname.text from fullname; -- error
ERROR: column fullname.text does not exist ERROR: column fullname.text does not exist
LINE 1: select fullname.text from fullname; LINE 1: select fullname.text from fullname;
@@ -987,7 +988,8 @@ select text(row('Jim', 'Beam')); -- error
ERROR: function text(record) does not exist ERROR: function text(record) does not exist
LINE 1: select text(row('Jim', 'Beam')); LINE 1: select text(row('Jim', 'Beam'));
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select (row('Jim', 'Beam')).text; -- error select (row('Jim', 'Beam')).text; -- error
ERROR: could not identify column "text" in record data type ERROR: could not identify column "text" in record data type
LINE 1: select (row('Jim', 'Beam')).text; LINE 1: select (row('Jim', 'Beam')).text;

View File

@@ -1175,7 +1175,8 @@ select * from int8_tbl where q1 in (select c1 from inner_text);
ERROR: operator does not exist: bigint = text ERROR: operator does not exist: bigint = text
LINE 1: select * from int8_tbl where q1 in (select c1 from inner_tex... LINE 1: select * from int8_tbl where q1 in (select c1 from inner_tex...
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
begin; begin;
-- make an operator to allow it to succeed -- make an operator to allow it to succeed
create function bogus_int8_text_eq(int8, text) returns boolean create function bogus_int8_text_eq(int8, text) returns boolean

View File

@@ -229,7 +229,7 @@ select nonempty('');
ERROR: function nonempty(unknown) does not exist ERROR: function nonempty(unknown) does not exist
LINE 1: select nonempty(''); LINE 1: select nonempty('');
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: There is no function of that name.
select pg_temp.nonempty(''); select pg_temp.nonempty('');
ERROR: value for domain nonempty violates check constraint "nonempty_check" ERROR: value for domain nonempty violates check constraint "nonempty_check"
-- other syntax matches rules for tables -- other syntax matches rules for tables

View File

@@ -27,7 +27,8 @@ select length(42);
ERROR: function length(integer) does not exist ERROR: function length(integer) does not exist
LINE 1: select length(42); LINE 1: select length(42);
^ ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. DETAIL: No function of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- But as a special exception for usability's sake, we still allow implicit -- But as a special exception for usability's sake, we still allow implicit
-- casting to text in concatenations, so long as the other input is text or -- casting to text in concatenations, so long as the other input is text or
-- an unknown literal. So these work: -- an unknown literal. So these work:
@@ -48,7 +49,8 @@ select 3 || 4.0;
ERROR: operator does not exist: integer || numeric ERROR: operator does not exist: integer || numeric
LINE 1: select 3 || 4.0; LINE 1: select 3 || 4.0;
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
/* /*
* various string functions * various string functions
*/ */

View File

@@ -157,7 +157,8 @@ SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL;
ERROR: operator is not unique: time without time zone + time without time zone ERROR: operator is not unique: time without time zone + time without time zone
LINE 1: SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL; LINE 1: SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL;
^ ^
HINT: Could not choose a best candidate operator. You might need to add explicit type casts. DETAIL: Could not choose a best candidate operator.
HINT: You might need to add explicit type casts.
-- --
-- test EXTRACT -- test EXTRACT
-- --

View File

@@ -174,7 +174,8 @@ SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TIMETZ_TBL;
ERROR: operator does not exist: time with time zone + time with time zone ERROR: operator does not exist: time with time zone + time with time zone
LINE 1: SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TI... LINE 1: SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TI...
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- --
-- test EXTRACT -- test EXTRACT
-- --

View File

@@ -175,7 +175,8 @@ SELECT n, pg_typeof(n) FROM t;
ERROR: operator does not exist: text + integer ERROR: operator does not exist: text + integer
LINE 4: SELECT n+1 FROM t WHERE n < 10 LINE 4: SELECT n+1 FROM t WHERE n < 10
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- Deeply nested WITH caused a list-munging problem in v13 -- Deeply nested WITH caused a list-munging problem in v13
-- Detection of cross-references and self-references -- Detection of cross-references and self-references
WITH RECURSIVE w1(c1) AS WITH RECURSIVE w1(c1) AS

View File

@@ -110,22 +110,26 @@ select '1'::xid < '2'::xid;
ERROR: operator does not exist: xid < xid ERROR: operator does not exist: xid < xid
LINE 1: select '1'::xid < '2'::xid; LINE 1: select '1'::xid < '2'::xid;
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select '1'::xid <= '2'::xid; select '1'::xid <= '2'::xid;
ERROR: operator does not exist: xid <= xid ERROR: operator does not exist: xid <= xid
LINE 1: select '1'::xid <= '2'::xid; LINE 1: select '1'::xid <= '2'::xid;
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select '1'::xid > '2'::xid; select '1'::xid > '2'::xid;
ERROR: operator does not exist: xid > xid ERROR: operator does not exist: xid > xid
LINE 1: select '1'::xid > '2'::xid; LINE 1: select '1'::xid > '2'::xid;
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
select '1'::xid >= '2'::xid; select '1'::xid >= '2'::xid;
ERROR: operator does not exist: xid >= xid ERROR: operator does not exist: xid >= xid
LINE 1: select '1'::xid >= '2'::xid; LINE 1: select '1'::xid >= '2'::xid;
^ ^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts. DETAIL: No operator of that name accepts the given argument types.
HINT: You might need to add explicit type casts.
-- we want them for xid8 though -- we want them for xid8 though
select '1'::xid8 < '2'::xid8, '2'::xid8 < '2'::xid8, '2'::xid8 < '1'::xid8; select '1'::xid8 < '2'::xid8, '2'::xid8 < '2'::xid8, '2'::xid8 < '1'::xid8;
?column? | ?column? | ?column? ?column? | ?column? | ?column?

View File

@@ -22,6 +22,13 @@ CREATE OPERATOR #%# (
-- Test operator created above -- Test operator created above
SELECT @#@ 24; SELECT @#@ 24;
-- Test error cases
select @@##@@ 24; -- no such operator
set search_path = pg_catalog;
select @#@ 24; -- wrong schema
reset search_path;
select @#@ 24.0; -- wrong data type
-- Test comments -- Test comments
COMMENT ON OPERATOR ###### (NONE, int4) IS 'bad prefix'; COMMENT ON OPERATOR ###### (NONE, int4) IS 'bad prefix';
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad postfix'; COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad postfix';

View File

@@ -873,6 +873,26 @@ select * from dfunc(1,c := 2,d := 3); -- fail, no value for b
drop function dfunc(int, int, int, int); drop function dfunc(int, int, int, int);
create function xleast(x numeric, variadic arr numeric[])
returns numeric as $$
select least(x, min(arr[i])) from generate_subscripts(arr, 1) g(i);
$$ language sql;
select xleast(x => 1, variadic arr => array[2,3]);
select xleast(1, variadic arr => array[2,3]);
set search_path = pg_catalog;
select xleast(1, variadic arr => array[2,3]); -- wrong schema
reset search_path;
select xleast(foo => 1, variadic arr => array[2,3]); -- wrong argument name
select xleast(x => 1, variadic array[2,3]); -- misuse of mixed notation
select xleast(1, variadic x => array[2,3]); -- misuse of mixed notation
select xleast(arr => array[1], variadic x => 3); -- wrong arg is VARIADIC
select xleast(arr => array[1], x => 3); -- failed to use VARIADIC
select xleast(arr => 1, variadic x => array[2,3]); -- mixed-up args
drop function xleast(x numeric, variadic arr numeric[]);
-- test with different parameter types -- test with different parameter types
create function dfunc(a varchar, b numeric, c date = current_date) create function dfunc(a varchar, b numeric, c date = current_date)
returns table (a varchar, b numeric, c date) as $$ returns table (a varchar, b numeric, c date) as $$