/* Possible error codes from LookupFuncNameInternal */ typedefenum
{
FUNCLOOKUP_NOSUCHFUNC,
FUNCLOOKUP_AMBIGUOUS,
} FuncLookupError;
staticvoid unify_hypothetical_args(ParseState *pstate,
List *fargs, int numAggregatedArgs,
Oid *actual_arg_types, Oid *declared_arg_types); static Oid FuncNameAsType(List *funcname); static Node *ParseComplexProjection(ParseState *pstate, constchar *funcname,
Node *first_arg, int location); static Oid LookupFuncNameInternal(ObjectType objtype, List *funcname, int nargs, const Oid *argtypes, bool include_out_arguments, bool missing_ok,
FuncLookupError *lookupError);
/* *Mostoftherestoftheparserjustassumesthatfunctionsdonothave *morethanFUNC_MAX_ARGSparameters.Wehavetotestheretoprotect *againstarrayoverruns,etc.Ofcourse,thismaynotbeafunction, *butthetestdoesn'thurt.
*/ if (list_length(fargs) > FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("cannot pass more than %d argument to a function", "cannot pass more than %d arguments to a function",
FUNC_MAX_ARGS,
FUNC_MAX_ARGS),
parser_errposition(pstate, location)));
/* If this is a CALL, reject things that aren't procedures */ if (proc_call &&
(fdresult == FUNCDETAIL_NORMAL ||
fdresult == FUNCDETAIL_AGGREGATE ||
fdresult == FUNCDETAIL_WINDOWFUNC ||
fdresult == FUNCDETAIL_COERCION))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not a procedure",
func_signature_string(funcname, nargs,
argnames,
actual_arg_types)),
errhint("To call a function, use SELECT."),
parser_errposition(pstate, location))); /* Conversely, if not a CALL, reject procedures */ if (fdresult == FUNCDETAIL_PROCEDURE && !proc_call)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is a procedure",
func_signature_string(funcname, nargs,
argnames,
actual_arg_types)),
errhint("To call a procedure, use CALL."),
parser_errposition(pstate, location)));
if (fdresult == FUNCDETAIL_NORMAL ||
fdresult == FUNCDETAIL_PROCEDURE ||
fdresult == FUNCDETAIL_COERCION)
{ /* *Inthesecases,complainiftherewasanythingindicatingitmust *beanaggregateorwindowfunction.
*/ if (agg_star)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s(*) specified, but %s is not an aggregate function",
NameListToString(funcname),
NameListToString(funcname)),
parser_errposition(pstate, location))); if (agg_distinct)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("DISTINCT specified, but %s is not an aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location))); if (agg_within_group)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("WITHIN GROUP specified, but %s is not an aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location))); if (agg_order != NIL)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("ORDER BY specified, but %s is not an aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location))); if (agg_filter)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("FILTER specified, but %s is not an aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location))); if (over)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("OVER specified, but %s is not a window function nor an aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location)));
}
/* *Sofarsogood,sodosomefdresult-type-specificprocessing.
*/ if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE)
{ /* Nothing special to do for these cases. */
} elseif (fdresult == FUNCDETAIL_AGGREGATE)
{ /* *It'sanaggregate;fetchneededinfofromthepg_aggregateentry.
*/
HeapTuple tup;
Form_pg_aggregate classForm; int catDirectArgs;
tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcid)); if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for aggregate %u", funcid);
classForm = (Form_pg_aggregate) GETSTRUCT(tup);
aggkind = classForm->aggkind;
catDirectArgs = classForm->aggnumdirectargs;
ReleaseSysCache(tup);
/* Now check various disallowed cases. */ if (AGGKIND_IS_ORDERED_SET(aggkind))
{ int numAggregatedArgs; int numDirectArgs;
if (!agg_within_group)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("WITHIN GROUP is required for ordered-set aggregate %s",
NameListToString(funcname)),
parser_errposition(pstate, location))); if (over)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("OVER is not supported for ordered-set aggregate %s",
NameListToString(funcname)),
parser_errposition(pstate, location))); /* gram.y rejects DISTINCT + WITHIN GROUP */
Assert(!agg_distinct); /* gram.y rejects VARIADIC + WITHIN GROUP */
Assert(!func_variadic);
if (!OidIsValid(vatype))
{ /* Test is simple if aggregate isn't variadic */ if (numDirectArgs != catDirectArgs)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs,
argnames,
actual_arg_types)),
errhint_plural("There is an ordered-set aggregate %s, but it requires %d direct argument, not %d.", "There is an ordered-set aggregate %s, but it requires %d direct arguments, not %d.",
catDirectArgs,
NameListToString(funcname),
catDirectArgs, numDirectArgs),
parser_errposition(pstate, location)));
} else
{ /* *Ifit'svariadic,wehavetwocasesdependingonwhether *theaggwas"...ORDERBYVARIADIC"or"...,VARIADICORDER *BYVARIADIC".It'sthelatterifcatDirectArgsequals *pronargs;tosaveacataloglookup,wereverse-engineer *pronargsfromtheinfowegotfromfunc_get_detail.
*/ int pronargs;
pronargs = nargs; if (nvargs > 1)
pronargs -= nvargs - 1; if (catDirectArgs < pronargs)
{ /* VARIADIC isn't part of direct args, so still easy */ if (numDirectArgs != catDirectArgs)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs,
argnames,
actual_arg_types)),
errhint_plural("There is an ordered-set aggregate %s, but it requires %d direct argument, not %d.", "There is an ordered-set aggregate %s, but it requires %d direct arguments, not %d.",
catDirectArgs,
NameListToString(funcname),
catDirectArgs, numDirectArgs),
parser_errposition(pstate, location)));
} else
{ /* *Bothdirectandaggregatedargsweredeclaredvariadic. *Forastandardordered-setaggregate,it'sokayaslong *astherearen'ttoofewdirectargs.Fora *hypothetical-setaggregate,weassumethatthe *hypotheticalargumentsarethosethatmatchedthe *variadicparameter;theremustbejustasmanyofthem *asthereareaggregatedarguments.
*/ if (aggkind == AGGKIND_HYPOTHETICAL)
{ if (nvargs != 2 * numAggregatedArgs)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs,
argnames,
actual_arg_types)),
errhint("To use the hypothetical-set aggregate %s, the number of hypothetical direct arguments (here %d) must match the number of ordering columns (here %d).",
NameListToString(funcname),
nvargs - numAggregatedArgs, numAggregatedArgs),
parser_errposition(pstate, location)));
} else
{ if (nvargs <= numAggregatedArgs)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs,
argnames,
actual_arg_types)),
errhint_plural("There is an ordered-set aggregate %s, but it requires at least %d direct argument.", "There is an ordered-set aggregate %s, but it requires at least %d direct arguments.",
catDirectArgs,
NameListToString(funcname),
catDirectArgs),
parser_errposition(pstate, location)));
}
}
}
/* Check type matching of hypothetical arguments */ if (aggkind == AGGKIND_HYPOTHETICAL)
unify_hypothetical_args(pstate, fargs, numAggregatedArgs,
actual_arg_types, declared_arg_types);
} else
{ /* Normal aggregate, so it can't have WITHIN GROUP */ if (agg_within_group)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not an ordered-set aggregate, so it cannot have WITHIN GROUP",
NameListToString(funcname)),
parser_errposition(pstate, location)));
}
} elseif (fdresult == FUNCDETAIL_WINDOWFUNC)
{ /* *Truewindowfunctionsmustbecalledwithawindowdefinition.
*/ if (!over)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("window function %s requires an OVER clause",
NameListToString(funcname)),
parser_errposition(pstate, location))); /* And, per spec, WITHIN GROUP isn't allowed */ if (agg_within_group)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("window function %s cannot have WITHIN GROUP",
NameListToString(funcname)),
parser_errposition(pstate, location)));
} elseif (fdresult == FUNCDETAIL_COERCION)
{ /* *Weinterpreteditasatypecoercion.coerce_typecanhandlethese *cases,sowhyduplicatecode...
*/ return coerce_type(pstate, linitial(fargs),
actual_arg_types[0], rettype, -1,
COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location);
} elseif (fdresult == FUNCDETAIL_MULTIPLE)
{ /* *Wefoundmultiplepossiblefunctionalmatches.Ifwearedealing *withattributenotation,returnfailure,lettingthecallerreport *"nosuchcolumn"(wealreadydeterminedtherewasn'tone).If *dealingwithfunctionnotation,report"ambiguousfunction", *regardlessofwhetherthere'salsoacolumnbythisname.
*/ if (is_column) return NULL;
if (proc_call)
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("procedure %s is not unique",
func_signature_string(funcname, nargs, argnames,
actual_arg_types)),
errhint("Could not choose a best candidate procedure. " "You might need to add explicit type casts."),
parser_errposition(pstate, location))); else
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("function %s is not unique",
func_signature_string(funcname, nargs, argnames,
actual_arg_types)),
errhint("Could not choose a best candidate function. " "You might need to add explicit type casts."),
parser_errposition(pstate, location)));
} else
{ /* *Notfoundasafunction.Ifwearedealingwithattribute *notation,returnfailure,lettingthecallerreport"nosuch *column"(wealreadydeterminedtherewasn'tone).
*/ if (is_column) return NULL;
/* *Checkforcolumnprojectioninterpretation,sincewedidn'tbefore.
*/ if (could_be_projection)
{
retval = ParseComplexProjection(pstate,
strVal(linitial(funcname)),
first_arg,
location); if (retval) return retval;
}
/* *Nofunction,andnocolumneither.Sincewe'redealingwith *functionnotation,report"functiondoesnotexist".
*/ if (list_length(agg_order) > 1 && !agg_within_group)
{ /* It's agg(x, ORDER BY y,z) ... perhaps misplaced ORDER BY */
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs, argnames,
actual_arg_types)),
errhint("No aggregate function matches the given name and argument types. " "Perhaps you misplaced ORDER BY; ORDER BY must appear " "after all regular arguments of the aggregate."),
parser_errposition(pstate, location)));
} elseif (proc_call)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("procedure %s does not exist",
func_signature_string(funcname, nargs, argnames,
actual_arg_types)),
errhint("No procedure matches the given name and argument types. " "You might need to add explicit type casts."),
parser_errposition(pstate, location))); else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs, argnames,
actual_arg_types)),
errhint("No function matches the given name and argument types. " "You might need to add explicit type casts."),
parser_errposition(pstate, location)));
}
/* probably shouldn't happen ... */ if (nargsplusdefs >= FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("cannot pass more than %d argument to a function", "cannot pass more than %d arguments to a function",
FUNC_MAX_ARGS,
FUNC_MAX_ARGS),
parser_errposition(pstate, location)));
newa->elements = vargs; /* assume all the variadic arguments were coerced to the same type */
newa->element_typeid = exprType((Node *) linitial(vargs));
newa->array_typeid = get_array_type(newa->element_typeid); if (!OidIsValid(newa->array_typeid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s",
format_type_be(newa->element_typeid)),
parser_errposition(pstate, exprLocation((Node *) vargs)))); /* array_collid will be set by parse_collate.c */
newa->multidims = false;
newa->location = exprLocation((Node *) vargs);
fargs = lappend(fargs, newa);
/* We could not have had VARIADIC marking before ... */
Assert(!func_variadic); /* ... but now, it's a VARIADIC call */
func_variadic = true;
}
if (!OidIsValid(get_base_element_type(va_arr_typid)))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("VARIADIC argument must be an array"),
parser_errposition(pstate,
exprLocation((Node *) llast(fargs)))));
}
/* if it returns a set, check that's OK */ if (retset)
check_srf_call_placement(pstate, last_srf, location);
/* build the appropriate output structure */ if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE)
{
FuncExpr *funcexpr = makeNode(FuncExpr);
funcexpr->funcid = funcid;
funcexpr->funcresulttype = rettype;
funcexpr->funcretset = retset;
funcexpr->funcvariadic = func_variadic;
funcexpr->funcformat = funcformat; /* funccollid and inputcollid will be set by parse_collate.c */
funcexpr->args = fargs;
funcexpr->location = location;
aggref->aggfnoid = funcid;
aggref->aggtype = rettype; /* aggcollid and inputcollid will be set by parse_collate.c */
aggref->aggtranstype = InvalidOid; /* will be set by planner */ /* aggargtypes will be set by transformAggregateCall */ /* aggdirectargs and args will be set by transformAggregateCall */ /* aggorder and aggdistinct will be set by transformAggregateCall */
aggref->aggfilter = agg_filter;
aggref->aggstar = agg_star;
aggref->aggvariadic = func_variadic;
aggref->aggkind = aggkind;
aggref->aggpresorted = false; /* agglevelsup will be set by transformAggregateCall */
aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */
aggref->aggno = -1; /* planner will set aggno and aggtransno */
aggref->aggtransno = -1;
aggref->location = location;
/* *Rejectattempttocallaparameterlessaggregatewithout(*) *syntax.Thisismerepedantrybutsomefolksinsisted...
*/ if (fargs == NIL && !agg_star && !agg_within_group)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s(*) must be used to call a parameterless aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location)));
if (retset)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregates cannot return sets"),
parser_errposition(pstate, location)));
/* *Wemightwanttosupportnamedargumentslater,butdisallowitfor *now.We'dneedtofigureouttheparsedrepresentation(shouldthe *NamedArgExprsgoaboveorbelowtheTargetEntrynodes?)andthen *teachtheplannertoreorderthelistproperly.Ormaybewecould *maketransformAggregateCalldothat?However,ifyou'dalsolike *toallowdefaultargumentsforaggregates,we'dneedtodoitin *planningtoavoidsemanticproblems.
*/ if (argnames != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("aggregates cannot use named arguments"),
parser_errposition(pstate, location)));
Assert(over); /* lack of this was checked above */
Assert(!agg_within_group); /* also checked above */
wfunc->winfnoid = funcid;
wfunc->wintype = rettype; /* wincollid and inputcollid will be set by parse_collate.c */
wfunc->args = fargs; /* winref will be set by transformWindowFuncCall */
wfunc->winstar = agg_star;
wfunc->winagg = (fdresult == FUNCDETAIL_AGGREGATE);
wfunc->aggfilter = agg_filter;
wfunc->runCondition = NIL;
wfunc->location = location;
/* *agg_starisallowedforaggregatefunctionsbutdistinctisn't
*/ if (agg_distinct)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("DISTINCT is not implemented for window functions"),
parser_errposition(pstate, location)));
/* *Rejectattempttocallaparameterlessaggregatewithout(*) *syntax.Thisismerepedantrybutsomefolksinsisted...
*/ if (wfunc->winagg && fargs == NIL && !agg_star)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s(*) must be used to call a parameterless aggregate function",
NameListToString(funcname)),
parser_errposition(pstate, location)));
/* *orderedaggsnotallowedinwindowsyet
*/ if (agg_order != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("aggregate ORDER BY is not implemented for window functions"),
parser_errposition(pstate, location)));
/* *FILTERisnotyetsupportedwithtruewindowfunctions
*/ if (!wfunc->winagg && agg_filter)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("FILTER is not implemented for non-aggregate window functions"),
parser_errposition(pstate, location)));
/* *Windowfunctionscan'teithertakeorreturnsets
*/ if (pstate->p_last_srf != last_srf)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("window function calls cannot contain set-returning function calls"),
errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
parser_errposition(pstate,
exprLocation(pstate->p_last_srf))));
/* protect local fixed-size arrays */ if (nargs > FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("cannot pass more than %d argument to a function", "cannot pass more than %d arguments to a function",
FUNC_MAX_ARGS,
FUNC_MAX_ARGS)));
/* *Ifanyinputtypesaredomains,reducethemtotheirbasetypes.This *ensuresthatwewillconsiderfunctionsonthebasetypetobe"exact *matches"intheexact-matchheuristic;italsomakesitpossibletodo *somethingusefulwiththetype-categoryheuristics.Notethatthis *makesitdifficult,butnotimpossible,tousefunctionsdeclaredto *takeadomainasaninputdatatype.Suchafunctionwillbeselected *overthebase-typefunctiononlyifitisanexactmatchatall *argumentpositions,andsowasalreadychosenbyourcaller. * *Whilewe'reatit,countthenumberofunknown-typeargumentsforuse *later.
*/
nunknowns = 0; for (i = 0; i < nargs; i++)
{ if (input_typeids[i] != UNKNOWNOID)
input_base_typeids[i] = getBaseType(input_typeids[i]); else
{ /* no need to call getBaseType on UNKNOWNOID */
input_base_typeids[i] = UNKNOWNOID;
nunknowns++;
}
}
/* *Runthroughallcandidatesandkeepthosewiththemostmatcheson *exacttypes.Keepallcandidatesifnonematch.
*/
ncandidates = 0;
nbestMatch = 0;
last_candidate = NULL; for (current_candidate = candidates;
current_candidate != NULL;
current_candidate = current_candidate->next)
{
current_typeids = current_candidate->args;
nmatch = 0; for (i = 0; i < nargs; i++)
{ if (input_base_typeids[i] != UNKNOWNOID &&
current_typeids[i] == input_base_typeids[i])
nmatch++;
}
/* take this one as the best choice so far? */ if ((nmatch > nbestMatch) || (last_candidate == NULL))
{
nbestMatch = nmatch;
candidates = current_candidate;
last_candidate = current_candidate;
ncandidates = 1;
} /* no worse than the last choice, so keep this one too? */ elseif (nmatch == nbestMatch)
{
last_candidate->next = current_candidate;
last_candidate = current_candidate;
ncandidates++;
} /* otherwise, don't bother keeping this one... */
}
if (last_candidate) /* terminate rebuilt list */
last_candidate->next = NULL;
if (ncandidates == 1) return candidates;
/* *Stilltoomanycandidates?Nowlookforcandidateswhichhaveeither *exactmatchesorpreferredtypesattheargsthatwillrequire *coercion.(Restrictionaddedin7.4:preferredtypemustbeofsame *categoryasinputtype;givenopreferencetocross-category *conversionstopreferredtypes.)Keepallcandidatesifnonematch.
*/ for (i = 0; i < nargs; i++) /* avoid multiple lookups */
slot_category[i] = TypeCategory(input_base_typeids[i]);
ncandidates = 0;
nbestMatch = 0;
last_candidate = NULL; for (current_candidate = candidates;
current_candidate != NULL;
current_candidate = current_candidate->next)
{
current_typeids = current_candidate->args;
nmatch = 0; for (i = 0; i < nargs; i++)
{ if (input_base_typeids[i] != UNKNOWNOID)
{ if (current_typeids[i] == input_base_typeids[i] ||
IsPreferredType(slot_category[i], current_typeids[i]))
nmatch++;
}
}
if (last_candidate) /* terminate rebuilt list */
last_candidate->next = NULL;
if (ncandidates == 1) return candidates;
/* *Stilltoomanycandidates?Tryassigningtypesfortheunknowninputs. * *Iftherearenounknowninputs,wehavenomoreheuristicsthatapply, *andmustfail.
*/ if (nunknowns == 0) return NULL; /* failed to select a best candidate */
current_typeids = current_candidate->args; for (i = 0; i < nargs; i++)
{ if (input_base_typeids[i] != UNKNOWNOID) continue;
current_type = current_typeids[i];
get_type_category_preferred(current_type,
¤t_category,
¤t_is_preferred); if (current_category != slot_category[i])
{
keepit = false; break;
} if (slot_has_preferred_type[i] && !current_is_preferred)
{
keepit = false; break;
}
} if (keepit)
{ /* keep this candidate */
last_candidate = current_candidate;
ncandidates++;
} else
{ /* forget this candidate */ if (last_candidate)
last_candidate->next = current_candidate->next; else
first_candidate = current_candidate->next;
}
}
/* if we found any matches, restrict our attention to those */ if (last_candidate)
{
candidates = first_candidate; /* terminate rebuilt list */
last_candidate->next = NULL;
}
if (ncandidates == 1) return candidates;
}
/* *Lastgasp:iftherearebothknown-andunknown-typeinputs,andall *theknowntypesarethesame,assumetheunknowninputsarealsothat *type,andseeifthatgivesusauniquematch.Ifso,usethatmatch. * *NOTE:forabinaryoperatorwithoneunknownandonenon-unknowninput, *wealreadytriedthisheuristicinbinary_oper_exact().However,that *codeonlyfindsexactmatches,whereasherewewillhandlematchesthat *involvecoercion,polymorphictyperesolution,etc.
*/ if (nunknowns < nargs)
{
Oid known_type = UNKNOWNOID;
for (i = 0; i < nargs; i++)
{ if (input_base_typeids[i] == UNKNOWNOID) continue; if (known_type == UNKNOWNOID) /* first known arg? */
known_type = input_base_typeids[i]; elseif (known_type != input_base_typeids[i])
{ /* oops, not all match */
known_type = UNKNOWNOID; break;
}
}
if (known_type != UNKNOWNOID)
{ /* okay, just one known type, apply the heuristic */ for (i = 0; i < nargs; i++)
input_base_typeids[i] = known_type;
ncandidates = 0;
last_candidate = NULL; for (current_candidate = candidates;
current_candidate != NULL;
current_candidate = current_candidate->next)
{
current_typeids = current_candidate->args; if (can_coerce_type(nargs, input_base_typeids, current_typeids,
COERCION_IMPLICIT))
{ if (++ncandidates > 1) break; /* not unique, give up */
last_candidate = current_candidate;
}
} if (ncandidates == 1)
{ /* successfully identified a unique match */
last_candidate->next = NULL; return last_candidate;
}
}
}
return NULL; /* failed to select a best candidate */
} /* func_select_candidate() */
/* func_get_detail() * *Findthenamedfunctioninthesystemcatalogs. * *Attempttofindthenamedfunctioninthesystemcatalogswith *argumentsexactlyasspecified,sothatthenormalcase(exactmatch) *isasquickaspossible. * *Ifanexactmatchisn'tfound: *1)checkforpossibleinterpretationasatypecoercionrequest *2)applytheambiguous-functionresolutionrules * *Returnvalues*funcidthrough*true_typeidsreceiveinfoaboutthefunction. *Ifargdefaultsisn'tNULL,*argdefaultsreceivesalistofanydefault *argumentexpressionsthatneedtobeaddedtothegivenarguments. * *Whenprocessinganamed-ormixed-notationcall(ie,fargnamesisn'tNIL), *thereturnedtrue_typeidsandargdefaultsareorderedaccordingtothe *call'sargumentordering:firstanypositionalarguments,thenthenamed *arguments,thendefaultedarguments(ifneededandallowedby *expand_defaults).Somecareisneededifthisinformationistobecompared *tothefunction'spg_procentry,butinpracticethecallercanusually *justworkwiththecall'sargumentordering. * *Werelyprimarilyonfargnames/nargs/argtypesastheargumentdescription. *Theactualexpressionnodelistispassedinfargssothatwecancheck *fortypecoercionofaconstant.Somecallerspassfargs==NILindicating *theydon'tneedthatcheckmade.Notealsothatwhenfargnamesisn'tNIL, *thefargslistmustbepassedifthecallerwantsactualargumentposition *informationtobereturnedintotheNamedArgExprnodes.
*/
FuncDetailCode
func_get_detail(List *funcname,
List *fargs,
List *fargnames, int nargs,
Oid *argtypes, bool expand_variadic, bool expand_defaults, bool include_out_arguments,
Oid *funcid, /* return value */
Oid *rettype, /* return value */ bool *retset, /* return value */ int *nvargs, /* return value */
Oid *vatype, /* return value */
Oid **true_typeids, /* return value */
List **argdefaults) /* optional return value */
{
FuncCandidateList raw_candidates;
FuncCandidateList best_candidate;
/* Get list of possible candidates from namespace search */
raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames,
expand_variadic, expand_defaults,
include_out_arguments, false);
/* *Quicklycheckifthereisanexactmatchtotheinputdatatypes(there *canbeonlyone)
*/ for (best_candidate = raw_candidates;
best_candidate != NULL;
best_candidate = best_candidate->next)
{ /* if nargs==0, argtypes can be null; don't pass that to memcmp */ if (nargs == 0 ||
memcmp(argtypes, best_candidate->args, nargs * sizeof(Oid)) == 0) break;
}
/* Delete any unused defaults from the returned list */ if (best_candidate->argnumbers != NULL)
{ /* *Thisisabittrickyinnamednotation,sincethesupplied *argumentscouldreplaceanysubsetofthedefaults.We *workbymakingabitmapsetoftheargnumbersofdefaulted *arguments,thenscanningthedefaultslistandselecting *theneededitems.(Thisassumesthatdefaultedarguments *shouldbesuppliedintheirpositionalorder.)
*/
Bitmapset *defargnumbers; int *firstdefarg;
List *newdefaults;
ListCell *lc; int i;
defargnumbers = NULL;
firstdefarg = &best_candidate->argnumbers[best_candidate->nargs - best_candidate->ndargs]; for (i = 0; i < best_candidate->ndargs; i++)
defargnumbers = bms_add_member(defargnumbers,
firstdefarg[i]);
newdefaults = NIL;
i = best_candidate->nominalnargs - pform->pronargdefaults;
foreach(lc, defaults)
{ if (bms_is_member(i, defargnumbers))
newdefaults = lappend(newdefaults, lfirst(lc));
i++;
}
Assert(list_length(newdefaults) == best_candidate->ndargs);
bms_free(defargnumbers);
*argdefaults = newdefaults;
} else
{ /* *Defaultsforpositionalnotationarelotseasier;just *removeanyunwantedonesfromthefront.
*/ int ndelete;
switch (pform->prokind)
{ case PROKIND_AGGREGATE:
result = FUNCDETAIL_AGGREGATE; break; case PROKIND_FUNCTION:
result = FUNCDETAIL_NORMAL; break; case PROKIND_PROCEDURE:
result = FUNCDETAIL_PROCEDURE; break; case PROKIND_WINDOW:
result = FUNCDETAIL_WINDOWFUNC; break; default:
elog(ERROR, "unrecognized prokind: %c", pform->prokind);
result = FUNCDETAIL_NORMAL; /* keep compiler quiet */ break;
}
ReleaseSysCache(ftup); return result;
}
return FUNCDETAIL_NOTFOUND;
}
/* *unify_hypothetical_args() * *Ensurethateachhypotheticaldirectargumentofahypothetical-set *aggregatehasthesametypeasthecorrespondingaggregatedargument. *Modifytheexpressionsinthefargslist,ifnecessary,andupdate *actual_arg_types[]. * *Iftheaggdeclareditsargsnon-ANY(evenANYELEMENT),weneedonlya *sanitycheckthatthedeclaredtypesmatch;make_fn_argumentswillcoerce *theactualargumentstomatchthedeclaredones.Butifthedeclaration *isANY,nothingwillhappeninmake_fn_arguments,soweneedtofixany *mismatchhere.WeusethesametyperesolutionlogicasUNIONetc.
*/ staticvoid
unify_hypothetical_args(ParseState *pstate,
List *fargs, int numAggregatedArgs,
Oid *actual_arg_types,
Oid *declared_arg_types)
{ int numDirectArgs,
numNonHypotheticalArgs; int hargpos;
numDirectArgs = list_length(fargs) - numAggregatedArgs;
numNonHypotheticalArgs = numDirectArgs - numAggregatedArgs; /* safety check (should only trigger with a misdeclared agg) */ if (numNonHypotheticalArgs < 0)
elog(ERROR, "incorrect number of arguments to hypothetical-set aggregate");
/* Check each hypothetical arg and corresponding aggregated arg */ for (hargpos = numNonHypotheticalArgs; hargpos < numDirectArgs; hargpos++)
{ int aargpos = numDirectArgs + (hargpos - numNonHypotheticalArgs);
ListCell *harg = list_nth_cell(fargs, hargpos);
ListCell *aarg = list_nth_cell(fargs, aargpos);
Oid commontype;
int32 commontypmod;
/* A mismatch means AggregateCreate didn't check properly ... */ if (declared_arg_types[hargpos] != declared_arg_types[aargpos])
elog(ERROR, "hypothetical-set aggregate has inconsistent declared argument types");
/* No need to unify if make_fn_arguments will coerce */ if (declared_arg_types[hargpos] != ANYOID) continue;
/* *make_fn_arguments() * *Giventheactualargumentexpressionsforafunction,andthedesired *inputtypesforthefunction,addanynecessarytypecastingtothe *expressiontree.Callershouldalreadyhaveverifiedthatcastingis *allowed. * *Caution:givenargumentlistismodifiedin-place. * *Aswithcoerce_type,pstatemaybeNULLifnospecialunknown-Param *processingiswanted.
*/ void
make_fn_arguments(ParseState *pstate,
List *fargs,
Oid *actual_arg_types,
Oid *declared_arg_types)
{
ListCell *current_fargs; int i = 0;
foreach(current_fargs, fargs)
{ /* types don't match? then force coercion using a function call... */ if (actual_arg_types[i] != declared_arg_types[i])
{
Node *node = (Node *) lfirst(current_fargs);
/* *func_signature_string *Asabove,butfunctionnameispassedasaqualifiednamelist.
*/ constchar *
func_signature_string(List *funcname, int nargs,
List *argnames, const Oid *argtypes)
{ return funcname_signature_string(NameListToString(funcname),
nargs, argnames, argtypes);
}
/* *LookupFuncNameInternal *WorkhorseforLookupFuncName/LookupFuncWithArgs * *Inanerrorsituation,e.g.can'tfindthefunction,thenwereturn *InvalidOidandset*lookupErrortoindicatewhatwentwrong. * *Possibleerrors: *FUNCLOOKUP_NOSUCHFUNC:wecan'tfindafunctionofthisname. *FUNCLOOKUP_AMBIGUOUS:morethanonefunctionmatches.
*/ static Oid
LookupFuncNameInternal(ObjectType objtype, List *funcname, int nargs, const Oid *argtypes, bool include_out_arguments, bool missing_ok,
FuncLookupError *lookupError)
{
Oid result = InvalidOid;
FuncCandidateList clist;
/* NULL argtypes allowed for nullary functions only */
Assert(argtypes != NULL || nargs == 0);
/* Always set *lookupError, to forestall uninitialized-variable warnings */
*lookupError = FUNCLOOKUP_NOSUCHFUNC;
/* Get list of candidate objects */
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false,
include_out_arguments, missing_ok);
/* Scan list for a match to the arg types (if specified) and the objtype */ for (; clist != NULL; clist = clist->next)
{ /* Check arg type match, if specified */ if (nargs >= 0)
{ /* if nargs==0, argtypes can be null; don't pass that to memcmp */ if (nargs > 0 &&
memcmp(argtypes, clist->args, nargs * sizeof(Oid)) != 0) continue;
}
/* Check for duplicates reported by FuncnameGetCandidates */ if (!OidIsValid(clist->oid))
{
*lookupError = FUNCLOOKUP_AMBIGUOUS; return InvalidOid;
}
/* Check objtype match, if specified */ switch (objtype)
{ case OBJECT_FUNCTION: case OBJECT_AGGREGATE: /* Ignore procedures */ if (get_func_prokind(clist->oid) == PROKIND_PROCEDURE) continue; break; case OBJECT_PROCEDURE: /* Ignore non-procedures */ if (get_func_prokind(clist->oid) != PROKIND_PROCEDURE) continue; break; case OBJECT_ROUTINE: /* no restriction */ break; default:
Assert(false);
}
/* Check for multiple matches */ if (OidIsValid(result))
{
*lookupError = FUNCLOOKUP_AMBIGUOUS; return InvalidOid;
}
/* OK, we have a candidate */
result = clist->oid;
}
return result;
}
/* *LookupFuncName * *Givenapossibly-qualifiedfunctionnameandoptionallyasetofargument *types,lookupthefunction.Passnargs==-1toindicatethatthenumber *andtypesoftheargumentsareunspecified(thisisNOTthesameas *specifyingthattherearenoarguments). * *Ifthefunctionnameisnotschema-qualified,itissoughtinthecurrent *namespacesearchpath. * *Ifthefunctionisnotfound,wereturnInvalidOidifmissing_okistrue, *elseraiseanerror. * *Ifnargs==-1andmultiplefunctionsarefoundmatchingthisfunctionname *wewillraiseanambiguous-functionerror,regardlessofwhatmissing_okis *setto. * *Onlyfunctionswillbefound;procedureswillbeignoredevenifthey *matchthenameandargumenttypes.(However,wedon'ttroubletoreject *aggregatesorwindowfunctionshere.)
*/
Oid
LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
{
Oid funcoid;
FuncLookupError lookupError;
switch (lookupError)
{ case FUNCLOOKUP_NOSUCHFUNC: /* Let the caller deal with it when missing_ok is true */ if (missing_ok) return InvalidOid;
if (nargs < 0)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not find a function named \"%s\"",
NameListToString(funcname)))); else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(funcname, nargs,
NIL, argtypes)))); break;
case FUNCLOOKUP_AMBIGUOUS: /* Raise an error regardless of missing_ok */
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("function name \"%s\" is not unique",
NameListToString(funcname)),
errhint("Specify the argument list to select the function unambiguously."))); break;
}
return InvalidOid; /* Keep compiler quiet */
}
/* *LookupFuncWithArgs * *LikeLookupFuncName,buttheargumenttypesarespecifiedbyan *ObjectWithArgsnode.Also,thisfunctioncancheckwhethertheresultisa *function,procedure,oraggregate,basedontheobjtypeargument.Pass *OBJECT_ROUTINEtoacceptanyofthem. * *Forhistoricalreasons,wealsoacceptaggregateswhenlookingfora *function. * *Whenmissing_okistruewedon'tgenerateanyerrorformissingobjectsand *returnInvalidOid.Othertypesoferrorscanstillberaised,regardless *ofthevalueofmissing_ok.
*/
Oid
LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
{
Oid argoids[FUNC_MAX_ARGS]; int argcount; int nargs; int i;
ListCell *args_item;
Oid oid;
FuncLookupError lookupError;
argcount = list_length(func->objargs); if (argcount > FUNC_MAX_ARGS)
{ if (objtype == OBJECT_PROCEDURE)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("procedures cannot have more than %d argument", "procedures cannot have more than %d arguments",
FUNC_MAX_ARGS,
FUNC_MAX_ARGS))); else
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("functions cannot have more than %d argument", "functions cannot have more than %d arguments",
FUNC_MAX_ARGS,
FUNC_MAX_ARGS)));
}
/* Without mode marks, objargs surely includes all params */
Assert(list_length(func->objfuncargs) == argcount);
/* For objtype == OBJECT_PROCEDURE, we can ignore non-procedures */
poid = LookupFuncNameInternal(objtype, func->objname,
argcount, argoids, true, missing_ok,
&lookupError);
/* Combine results, handling ambiguity */ if (OidIsValid(poid))
{ if (OidIsValid(oid) && oid != poid)
{ /* oops, we got hits both ways, on different objects */
oid = InvalidOid;
lookupError = FUNCLOOKUP_AMBIGUOUS;
} else
oid = poid;
} elseif (lookupError == FUNCLOOKUP_AMBIGUOUS)
oid = InvalidOid;
}
}
if (OidIsValid(oid))
{ /* *Evenifwefoundthefunction,performvalidationthattheobjtype *matchestheprokindofthefoundfunction.Forhistoricalreasons *weallowtheobjtypeofFUNCTIONtoincludeaggregatesandwindow *functions;butwedrawthelineiftheobjectisaprocedure.That *isanewenoughfeaturethatthishistoricalruledoesnotapply. * *(Thischeckispartiallyredundantwiththeobjtypecheckin *LookupFuncNameInternal;butnotentirely,sinceweoftendon'ttell *LookupFuncNameInternaltoapplythatcheckatall.)
*/ switch (objtype)
{ case OBJECT_FUNCTION: /* Only complain if it's a procedure. */ if (get_func_prokind(oid) == PROKIND_PROCEDURE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not a function",
func_signature_string(func->objname, argcount,
NIL, argoids)))); break;
case OBJECT_PROCEDURE: /* Reject if found object is not a procedure. */ if (get_func_prokind(oid) != PROKIND_PROCEDURE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not a procedure",
func_signature_string(func->objname, argcount,
NIL, argoids)))); break;
case OBJECT_AGGREGATE: /* Reject if found object is not an aggregate. */ if (get_func_prokind(oid) != PROKIND_AGGREGATE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("function %s is not an aggregate",
func_signature_string(func->objname, argcount,
NIL, argoids)))); break;
return oid; /* All good */
} else
{ /* Deal with cases where the lookup failed */ switch (lookupError)
{ case FUNCLOOKUP_NOSUCHFUNC: /* Suppress no-such-func errors when missing_ok is true */ if (missing_ok) break;
switch (objtype)
{ case OBJECT_PROCEDURE: if (func->args_unspecified)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not find a procedure named \"%s\"",
NameListToString(func->objname)))); else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("procedure %s does not exist",
func_signature_string(func->objname, argcount,
NIL, argoids)))); break;
case OBJECT_AGGREGATE: if (func->args_unspecified)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not find an aggregate named \"%s\"",
NameListToString(func->objname)))); elseif (argcount == 0)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("aggregate %s(*) does not exist",
NameListToString(func->objname)))); else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("aggregate %s does not exist",
func_signature_string(func->objname, argcount,
NIL, argoids)))); break;
default: /* FUNCTION and ROUTINE */ if (func->args_unspecified)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not find a function named \"%s\"",
NameListToString(func->objname)))); else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(func->objname, argcount,
NIL, argoids)))); break;
} break;
case FUNCLOOKUP_AMBIGUOUS: switch (objtype)
{ case OBJECT_FUNCTION:
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("function name \"%s\" is not unique",
NameListToString(func->objname)),
func->args_unspecified ?
errhint("Specify the argument list to select the function unambiguously.") : 0)); break; case OBJECT_PROCEDURE:
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("procedure name \"%s\" is not unique",
NameListToString(func->objname)),
func->args_unspecified ?
errhint("Specify the argument list to select the procedure unambiguously.") : 0)); break; case OBJECT_AGGREGATE:
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("aggregate name \"%s\" is not unique",
NameListToString(func->objname)),
func->args_unspecified ?
errhint("Specify the argument list to select the aggregate unambiguously.") : 0)); break; case OBJECT_ROUTINE:
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("routine name \"%s\" is not unique",
NameListToString(func->objname)),
func->args_unspecified ?
errhint("Specify the argument list to select the routine unambiguously.") : 0)); break;
/* *Checktoseeiftheset-returningfunctionisinaninvalidplace *withinthequery.Basically,wedon'tallowSRFsanywhereexceptin *thetargetlist(whichincludesGROUPBY/ORDERBYexpressions),VALUES, *andfunctionsinFROM. * *Forbrevitywesupporttwoschemesforreportinganerrorhere:set *"err"toacustommessage,orset"errkind"trueiftheerrorcontext *issufficientlyidentifiedbywhatParseExprKindNamewillreturn,*and* *whatitwillreturnisjustaSQLkeyword.(Otherwise,useacustom *messagetoavoidcreatingtranslationproblems.)
*/
err = NULL;
errkind = false; switch (pstate->p_expr_kind)
{ case EXPR_KIND_NONE:
Assert(false); /* can't happen */ break; case EXPR_KIND_OTHER: /* Accept SRF here; caller must throw error if wanted */ break; case EXPR_KIND_JOIN_ON: case EXPR_KIND_JOIN_USING:
err = _("set-returning functions are not allowed in JOIN conditions"); break; case EXPR_KIND_FROM_SUBSELECT: /* can't get here, but just in case, throw an error */
errkind = true; break; case EXPR_KIND_FROM_FUNCTION: /* okay, but we don't allow nested SRFs here */ /* errmsg is chosen to match transformRangeFunction() */ /* errposition should point to the inner SRF */ if (pstate->p_last_srf != last_srf)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("set-returning functions must appear at top level of FROM"),
parser_errposition(pstate,
exprLocation(pstate->p_last_srf)))); break; case EXPR_KIND_WHERE:
errkind = true; break; case EXPR_KIND_POLICY:
err = _("set-returning functions are not allowed in policy expressions"); break; case EXPR_KIND_HAVING:
errkind = true; break; case EXPR_KIND_FILTER:
errkind = true; break; case EXPR_KIND_WINDOW_PARTITION: case EXPR_KIND_WINDOW_ORDER: /* okay, these are effectively GROUP BY/ORDER BY */
pstate->p_hasTargetSRFs = true; break; case EXPR_KIND_WINDOW_FRAME_RANGE: case EXPR_KIND_WINDOW_FRAME_ROWS: case EXPR_KIND_WINDOW_FRAME_GROUPS:
err = _("set-returning functions are not allowed in window definitions"); break; case EXPR_KIND_SELECT_TARGET: case EXPR_KIND_INSERT_TARGET: /* okay */
pstate->p_hasTargetSRFs = true; break; case EXPR_KIND_UPDATE_SOURCE: case EXPR_KIND_UPDATE_TARGET: /* disallowed because it would be ambiguous what to do */
errkind = true; break; case EXPR_KIND_GROUP_BY: case EXPR_KIND_ORDER_BY: /* okay */
pstate->p_hasTargetSRFs = true; break; case EXPR_KIND_DISTINCT_ON: /* okay */
pstate->p_hasTargetSRFs = true; break; case EXPR_KIND_LIMIT: case EXPR_KIND_OFFSET:
errkind = true; break; case EXPR_KIND_RETURNING: case EXPR_KIND_MERGE_RETURNING:
errkind = true; break; case EXPR_KIND_VALUES: /* SRFs are presently not supported by nodeValuesscan.c */
errkind = true; break; case EXPR_KIND_VALUES_SINGLE: /* okay, since we process this like a SELECT tlist */
pstate->p_hasTargetSRFs = true; break; case EXPR_KIND_MERGE_WHEN:
err = _("set-returning functions are not allowed in MERGE WHEN conditions"); break; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK:
err = _("set-returning functions are not allowed in check constraints"); break; case EXPR_KIND_COLUMN_DEFAULT: case EXPR_KIND_FUNCTION_DEFAULT:
err = _("set-returning functions are not allowed in DEFAULT expressions"); break; case EXPR_KIND_INDEX_EXPRESSION:
err = _("set-returning functions are not allowed in index expressions"); break; case EXPR_KIND_INDEX_PREDICATE:
err = _("set-returning functions are not allowed in index predicates"); break; case EXPR_KIND_STATS_EXPRESSION:
err = _("set-returning functions are not allowed in statistics expressions"); break; case EXPR_KIND_ALTER_COL_TRANSFORM:
err = _("set-returning functions are not allowed in transform expressions"); break; case EXPR_KIND_EXECUTE_PARAMETER:
err = _("set-returning functions are not allowed in EXECUTE parameters"); break; case EXPR_KIND_TRIGGER_WHEN:
err = _("set-returning functions are not allowed in trigger WHEN conditions"); break; case EXPR_KIND_PARTITION_BOUND:
err = _("set-returning functions are not allowed in partition bound"); break; case EXPR_KIND_PARTITION_EXPRESSION:
err = _("set-returning functions are not allowed in partition key expressions"); break; case EXPR_KIND_CALL_ARGUMENT:
err = _("set-returning functions are not allowed in CALL arguments"); break; case EXPR_KIND_COPY_WHERE:
err = _("set-returning functions are not allowed in COPY FROM WHERE conditions"); break; case EXPR_KIND_GENERATED_COLUMN:
err = _("set-returning functions are not allowed in column generation expressions"); break; case EXPR_KIND_CYCLE_MARK:
errkind = true; break;
/* *Thereisintentionallynodefault:casehere,sothatthe *compilerwillwarnifweaddanewParseExprKindwithout *extendingthisswitch.Ifwedoseeanunrecognizedvalueat *runtime,thebehaviorwillbethesameasforEXPR_KIND_OTHER, *whichissaneanyway.
*/
} if (err)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg_internal("%s", err),
parser_errposition(pstate, location))); if (errkind)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is name of a SQL construct, eg GROUP BY */
errmsg("set-returning functions are not allowed in %s",
ParseExprKindName(pstate->p_expr_kind)),
parser_errposition(pstate, location)));
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.87 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.