summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2025-09-16 12:17:02 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2025-09-16 12:17:02 -0400
commit83a56419457ec0eff2eddfed8eb3aba86bede9cc (patch)
treec93d0986e7d19c763c2d0965d98edc8d336b78ea /src/backend/utils/adt
parentc7b0cb367d3c6b007122457ad5deb659fe8cc266 (diff)
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
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/regproc.c19
-rw-r--r--src/backend/utils/adt/ruleutils.c2
2 files changed, 15 insertions, 6 deletions
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index af17a3421a0..e5c2246f2c9 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -71,6 +71,7 @@ regprocin(PG_FUNCTION_ARGS)
RegProcedure result;
List *names;
FuncCandidateList clist;
+ int fgc_flags;
/* Handle "-" or numeric OID */
if (parseDashOrOid(pro_name_or_oid, &result, escontext))
@@ -93,7 +94,8 @@ regprocin(PG_FUNCTION_ARGS)
if (names == NIL)
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)
ereturn(escontext, (Datum) 0,
@@ -164,13 +166,15 @@ regprocout(PG_FUNCTION_ARGS)
{
char *nspname;
FuncCandidateList clist;
+ int fgc_flags;
/*
* Would this proc be found (uniquely!) by regprocin? If not,
* qualify it.
*/
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 &&
clist->oid == proid)
nspname = NULL;
@@ -231,6 +235,7 @@ regprocedurein(PG_FUNCTION_ARGS)
int nargs;
Oid argtypes[FUNC_MAX_ARGS];
FuncCandidateList clist;
+ int fgc_flags;
/* Handle "-" or numeric OID */
if (parseDashOrOid(pro_name_or_oid, &result, escontext))
@@ -251,8 +256,8 @@ regprocedurein(PG_FUNCTION_ARGS)
escontext))
PG_RETURN_NULL();
- clist = FuncnameGetCandidates(names, nargs, NIL, false, false,
- false, true);
+ clist = FuncnameGetCandidates(names, nargs, NIL, false, false, false, true,
+ &fgc_flags);
for (; clist; clist = clist->next)
{
@@ -483,6 +488,7 @@ regoperin(PG_FUNCTION_ARGS)
Oid result;
List *names;
FuncCandidateList clist;
+ int fgc_flags;
/* Handle "0" or numeric OID */
if (parseNumericOid(opr_name_or_oid, &result, escontext))
@@ -502,7 +508,7 @@ regoperin(PG_FUNCTION_ARGS)
if (names == NIL)
PG_RETURN_NULL();
- clist = OpernameGetCandidates(names, '\0', true);
+ clist = OpernameGetCandidates(names, '\0', true, &fgc_flags);
if (clist == NULL)
ereturn(escontext, (Datum) 0,
@@ -572,13 +578,14 @@ regoperout(PG_FUNCTION_ARGS)
else
{
FuncCandidateList clist;
+ int fgc_flags;
/*
* Would this oper be found (uniquely!) by regoperin? If not,
* qualify it.
*/
clist = OpernameGetCandidates(list_make1(makeString(oprname)),
- '\0', false);
+ '\0', false, &fgc_flags);
if (clist != NULL && clist->next == NULL &&
clist->oid == oprid)
result = pstrdup(oprname);
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3d6e6bdbfd2..0408a95941d 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -13265,6 +13265,7 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
bool use_variadic;
char *nspname;
FuncDetailCode p_result;
+ int fgc_flags;
Oid p_funcid;
Oid p_rettype;
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)),
NIL, argnames, nargs, argtypes,
!use_variadic, true, false,
+ &fgc_flags,
&p_funcid, &p_rettype,
&p_retset, &p_nvargs, &p_vatype,
&p_true_typeids, NULL);