| /*------------------------------------------------------------------------- |
| * |
| * parse_func.c |
| * handle function calls in parser |
| * |
| * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| * |
| * |
| * IDENTIFICATION |
| * src/backend/parser/parse_func.c |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #include "postgres.h" |
| |
| #include "access/htup_details.h" |
| #include "catalog/pg_aggregate.h" |
| #include "catalog/pg_proc.h" |
| #include "catalog/pg_proc_callback.h" |
| #include "catalog/pg_type.h" |
| #include "funcapi.h" |
| #include "lib/stringinfo.h" |
| #include "nodes/makefuncs.h" |
| #include "nodes/nodeFuncs.h" |
| #include "parser/parse_agg.h" |
| #include "parser/parse_clause.h" |
| #include "parser/parse_coerce.h" |
| #include "parser/parse_expr.h" |
| #include "parser/parse_func.h" |
| #include "parser/parse_relation.h" |
| #include "parser/parse_target.h" |
| #include "parser/parse_type.h" |
| #include "utils/builtins.h" |
| #include "utils/lsyscache.h" |
| #include "utils/syscache.h" |
| |
| |
| /* Possible error codes from LookupFuncNameInternal */ |
| typedef enum |
| { |
| FUNCLOOKUP_NOSUCHFUNC, |
| FUNCLOOKUP_AMBIGUOUS |
| } FuncLookupError; |
| |
| static void 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, const char *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); |
| |
| typedef struct |
| { |
| Node *parent; |
| } check_table_func_context; |
| |
| static bool |
| checkTableFunctions_walker(Node *node, check_table_func_context *context); |
| |
| /* |
| * Parse a function call |
| * |
| * For historical reasons, Postgres tries to treat the notations tab.col |
| * and col(tab) as equivalent: if a single-argument function call has an |
| * argument of complex type and the (unqualified) function name matches |
| * any attribute of the type, we can interpret it as a column projection. |
| * Conversely a function of a single complex-type argument can be written |
| * like a column reference, allowing functions to act like computed columns. |
| * |
| * If both interpretations are possible, we prefer the one matching the |
| * syntactic form, but otherwise the form does not matter. |
| * |
| * Hence, both cases come through here. If fn is null, we're dealing with |
| * column syntax not function syntax. In the function-syntax case, |
| * the FuncCall struct is needed to carry various decoration that applies |
| * to aggregate and window functions. |
| * |
| * Also, when fn is null, we return NULL on failure rather than |
| * reporting a no-such-function error. |
| * |
| * The argument expressions (in fargs) must have been transformed |
| * already. However, nothing in *fn has been transformed. |
| * |
| * last_srf should be a copy of pstate->p_last_srf from just before we |
| * started transforming fargs. If the caller knows that fargs couldn't |
| * contain any SRF calls, last_srf can just be pstate->p_last_srf. |
| * |
| * proc_call is true if we are considering a CALL statement, so that the |
| * name must resolve to a procedure name, not anything else. This flag |
| * also specifies that the argument list includes any OUT-mode arguments. |
| */ |
| Node * |
| ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, |
| Node *last_srf, FuncCall *fn, bool proc_call, int location) |
| { |
| bool is_column = (fn == NULL); |
| List *agg_order = (fn ? fn->agg_order : NIL); |
| Expr *agg_filter = NULL; |
| WindowDef *over = (fn ? fn->over : NULL); |
| bool agg_within_group = (fn ? fn->agg_within_group : false); |
| bool agg_star = (fn ? fn->agg_star : false); |
| bool agg_distinct = (fn ? fn->agg_distinct : false); |
| bool func_variadic = (fn ? fn->func_variadic : false); |
| CoercionForm funcformat = (fn ? fn->funcformat : COERCE_EXPLICIT_CALL); |
| bool could_be_projection; |
| Oid rettype; |
| Oid funcid; |
| ListCell *l; |
| Node *first_arg = NULL; |
| int nargs; |
| int nargsplusdefs; |
| Oid actual_arg_types[FUNC_MAX_ARGS]; |
| Oid *declared_arg_types; |
| List *argnames; |
| List *argdefaults; |
| Node *retval; |
| bool retset; |
| int nvargs; |
| Oid vatype; |
| FuncDetailCode fdresult; |
| char aggkind = 0; |
| ParseCallbackState pcbstate; |
| |
| /* |
| * If there's an aggregate filter, transform it using transformWhereClause |
| */ |
| if (fn && fn->agg_filter != NULL) |
| agg_filter = (Expr *) transformWhereClause(pstate, fn->agg_filter, |
| EXPR_KIND_FILTER, |
| "FILTER"); |
| |
| /* |
| * Most of the rest of the parser just assumes that functions do not have |
| * more than FUNC_MAX_ARGS parameters. We have to test here to protect |
| * against array overruns, etc. Of course, this may not be a function, |
| * but the test doesn't hurt. |
| */ |
| 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))); |
| |
| /* |
| * Extract arg type info in preparation for function lookup. |
| * |
| * If any arguments are Param markers of type VOID, we discard them from |
| * the parameter list. This is a hack to allow the JDBC driver to not have |
| * to distinguish "input" and "output" parameter symbols while parsing |
| * function-call constructs. Don't do this if dealing with column syntax, |
| * nor if we had WITHIN GROUP (because in that case it's critical to keep |
| * the argument count unchanged). |
| */ |
| nargs = 0; |
| foreach(l, fargs) |
| { |
| Node *arg = lfirst(l); |
| Oid argtype = exprType(arg); |
| |
| if (argtype == VOIDOID && IsA(arg, Param) && |
| !is_column && !agg_within_group) |
| { |
| fargs = foreach_delete_current(fargs, l); |
| continue; |
| } |
| |
| actual_arg_types[nargs++] = argtype; |
| } |
| |
| /* |
| * Check for named arguments; if there are any, build a list of names. |
| * |
| * We allow mixed notation (some named and some not), but only with all |
| * the named parameters after all the unnamed ones. So the name list |
| * corresponds to the last N actual parameters and we don't need any extra |
| * bookkeeping to match things up. |
| */ |
| argnames = NIL; |
| foreach(l, fargs) |
| { |
| Node *arg = lfirst(l); |
| |
| if (IsA(arg, NamedArgExpr)) |
| { |
| NamedArgExpr *na = (NamedArgExpr *) arg; |
| ListCell *lc; |
| |
| /* Reject duplicate arg names */ |
| foreach(lc, argnames) |
| { |
| if (strcmp(na->name, (char *) lfirst(lc)) == 0) |
| ereport(ERROR, |
| (errcode(ERRCODE_SYNTAX_ERROR), |
| errmsg("argument name \"%s\" used more than once", |
| na->name), |
| parser_errposition(pstate, na->location))); |
| } |
| argnames = lappend(argnames, na->name); |
| } |
| else |
| { |
| if (argnames != NIL) |
| ereport(ERROR, |
| (errcode(ERRCODE_SYNTAX_ERROR), |
| errmsg("positional argument cannot follow named argument"), |
| parser_errposition(pstate, exprLocation(arg)))); |
| } |
| } |
| |
| if (fargs) |
| { |
| first_arg = linitial(fargs); |
| Assert(first_arg != NULL); |
| } |
| |
| /* |
| * Decide whether it's legitimate to consider the construct to be a column |
| * projection. For that, there has to be a single argument of complex |
| * type, the function name must not be qualified, and there cannot be any |
| * syntactic decoration that'd require it to be a function (such as |
| * aggregate or variadic decoration, or named arguments). |
| */ |
| could_be_projection = (nargs == 1 && !proc_call && |
| agg_order == NIL && agg_filter == NULL && |
| !agg_star && !agg_distinct && over == NULL && |
| !func_variadic && argnames == NIL && |
| list_length(funcname) == 1 && |
| (actual_arg_types[0] == RECORDOID || |
| ISCOMPLEX(actual_arg_types[0]))); |
| |
| /* |
| * If it's column syntax, check for column projection case first. |
| */ |
| if (could_be_projection && is_column) |
| { |
| retval = ParseComplexProjection(pstate, |
| strVal(linitial(funcname)), |
| first_arg, |
| location); |
| if (retval) |
| return retval; |
| |
| /* |
| * If ParseComplexProjection doesn't recognize it as a projection, |
| * just press on. |
| */ |
| } |
| |
| /* |
| * func_get_detail looks up the function in the catalogs, does |
| * disambiguation for polymorphic functions, handles inheritance, and |
| * returns the funcid and type and set or singleton status of the |
| * function's return value. It also returns the true argument types to |
| * the function. |
| * |
| * Note: for a named-notation or variadic function call, the reported |
| * "true" types aren't really what is in pg_proc: the types are reordered |
| * to match the given argument order of named arguments, and a variadic |
| * argument is replaced by a suitable number of copies of its element |
| * type. We'll fix up the variadic case below. We may also have to deal |
| * with default arguments. |
| */ |
| |
| setup_parser_errposition_callback(&pcbstate, pstate, location); |
| |
| fdresult = func_get_detail(funcname, fargs, argnames, nargs, |
| actual_arg_types, |
| !func_variadic, true, proc_call, |
| &funcid, &rettype, &retset, |
| &nvargs, &vatype, |
| &declared_arg_types, &argdefaults); |
| |
| cancel_parser_errposition_callback(&pcbstate); |
| |
| /* |
| * Check for various wrong-kind-of-routine cases. |
| */ |
| |
| /* 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) |
| { |
| /* |
| * In these cases, complain if there was anything indicating it must |
| * be an aggregate or window function. |
| */ |
| 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))); |
| } |
| |
| /* |
| * So far so good, so do some fdresult-type-specific processing. |
| */ |
| if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE) |
| { |
| /* Nothing special to do for these cases. */ |
| } |
| else if (fdresult == FUNCDETAIL_AGGREGATE) |
| { |
| /* |
| * It's an aggregate; fetch needed info from the pg_aggregate entry. |
| */ |
| 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); |
| |
| /* |
| * Since func_get_detail was working with an undifferentiated list |
| * of arguments, it might have selected an aggregate that doesn't |
| * really match because it requires a different division of direct |
| * and aggregated arguments. Check that the number of direct |
| * arguments is actually OK; if not, throw an "undefined function" |
| * error, similarly to the case where a misplaced ORDER BY is used |
| * in a regular aggregate call. |
| */ |
| numAggregatedArgs = list_length(agg_order); |
| numDirectArgs = nargs - numAggregatedArgs; |
| Assert(numDirectArgs >= 0); |
| |
| 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 |
| { |
| /* |
| * If it's variadic, we have two cases depending on whether |
| * the agg was "... ORDER BY VARIADIC" or "..., VARIADIC ORDER |
| * BY VARIADIC". It's the latter if catDirectArgs equals |
| * pronargs; to save a catalog lookup, we reverse-engineer |
| * pronargs from the info we got from func_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 |
| { |
| /* |
| * Both direct and aggregated args were declared variadic. |
| * For a standard ordered-set aggregate, it's okay as long |
| * as there aren't too few direct args. For a |
| * hypothetical-set aggregate, we assume that the |
| * hypothetical arguments are those that matched the |
| * variadic parameter; there must be just as many of them |
| * as there are aggregated arguments. |
| */ |
| 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))); |
| } |
| } |
| else if (fdresult == FUNCDETAIL_WINDOWFUNC) |
| { |
| /* |
| * True window functions must be called with a window definition. |
| */ |
| 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))); |
| } |
| else if (fdresult == FUNCDETAIL_COERCION) |
| { |
| /* |
| * We interpreted it as a type coercion. coerce_type can handle these |
| * cases, so why duplicate code... |
| */ |
| return coerce_type(pstate, linitial(fargs), |
| actual_arg_types[0], rettype, -1, |
| COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location); |
| } |
| else if (fdresult == FUNCDETAIL_MULTIPLE) |
| { |
| /* |
| * We found multiple possible functional matches. If we are dealing |
| * with attribute notation, return failure, letting the caller report |
| * "no such column" (we already determined there wasn't one). If |
| * dealing with function notation, report "ambiguous function", |
| * regardless of whether there's also a column by this name. |
| */ |
| 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 |
| { |
| /* |
| * Not found as a function. If we are dealing with attribute |
| * notation, return failure, letting the caller report "no such |
| * column" (we already determined there wasn't one). |
| */ |
| if (is_column) |
| return NULL; |
| |
| /* |
| * Check for column projection interpretation, since we didn't before. |
| */ |
| if (could_be_projection) |
| { |
| retval = ParseComplexProjection(pstate, |
| strVal(linitial(funcname)), |
| first_arg, |
| location); |
| if (retval) |
| return retval; |
| } |
| |
| /* |
| * No function, and no column either. Since we're dealing with |
| * function notation, report "function does not exist". |
| */ |
| 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))); |
| } |
| else if (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))); |
| } |
| |
| /* |
| * If there are default arguments, we have to include their types in |
| * actual_arg_types for the purpose of checking generic type consistency. |
| * However, we do NOT put them into the generated parse node, because |
| * their actual values might change before the query gets run. The |
| * planner has to insert the up-to-date values at plan time. |
| */ |
| nargsplusdefs = nargs; |
| foreach(l, argdefaults) |
| { |
| Node *expr = (Node *) lfirst(l); |
| |
| /* 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))); |
| |
| actual_arg_types[nargsplusdefs++] = exprType(expr); |
| } |
| |
| /* |
| * enforce consistency with polymorphic argument and return types, |
| * possibly adjusting return type or declared_arg_types (which will be |
| * used as the cast destination by make_fn_arguments) |
| */ |
| rettype = enforce_generic_type_consistency(actual_arg_types, |
| declared_arg_types, |
| nargsplusdefs, |
| rettype, |
| false); |
| |
| /* perform the necessary typecasting of arguments */ |
| make_fn_arguments(pstate, fargs, actual_arg_types, declared_arg_types); |
| |
| /* |
| * If the function isn't actually variadic, forget any VARIADIC decoration |
| * on the call. (Perhaps we should throw an error instead, but |
| * historically we've allowed people to write that.) |
| */ |
| if (!OidIsValid(vatype)) |
| { |
| Assert(nvargs == 0); |
| func_variadic = false; |
| } |
| |
| /* |
| * If it's a variadic function call, transform the last nvargs arguments |
| * into an array --- unless it's an "any" variadic. |
| */ |
| if (nvargs > 0 && vatype != ANYOID) |
| { |
| ArrayExpr *newa = makeNode(ArrayExpr); |
| int non_var_args = nargs - nvargs; |
| List *vargs; |
| |
| Assert(non_var_args >= 0); |
| vargs = list_copy_tail(fargs, non_var_args); |
| fargs = list_truncate(fargs, non_var_args); |
| |
| 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 an "any" variadic is called with explicit VARIADIC marking, insist |
| * that the variadic parameter be of some array type. |
| */ |
| if (nargs > 0 && vatype == ANYOID && func_variadic) |
| { |
| Oid va_arr_typid = actual_arg_types[nargs - 1]; |
| |
| 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; |
| |
| retval = (Node *) funcexpr; |
| } |
| else if (fdresult == FUNCDETAIL_AGGREGATE && !over) |
| { |
| /* aggregate function */ |
| Aggref *aggref = makeNode(Aggref); |
| |
| 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; |
| |
| /* |
| * Reject attempt to call a parameterless aggregate without (*) |
| * syntax. This is mere pedantry but some folks insisted ... |
| * |
| * GPDB: We allow this in GPDB. |
| */ |
| #if 0 |
| 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))); |
| #endif |
| |
| if (retset) |
| ereport(ERROR, |
| (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
| errmsg("aggregates cannot return sets"), |
| parser_errposition(pstate, location))); |
| |
| /* |
| * We might want to support named arguments later, but disallow it for |
| * now. We'd need to figure out the parsed representation (should the |
| * NamedArgExprs go above or below the TargetEntry nodes?) and then |
| * teach the planner to reorder the list properly. Or maybe we could |
| * make transformAggregateCall do that? However, if you'd also like |
| * to allow default arguments for aggregates, we'd need to do it in |
| * planning to avoid semantic problems. |
| */ |
| if (argnames != NIL) |
| ereport(ERROR, |
| (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| errmsg("aggregates cannot use named arguments"), |
| parser_errposition(pstate, location))); |
| |
| /* parse_agg.c does additional aggregate-specific processing */ |
| transformAggregateCall(pstate, aggref, fargs, agg_order, agg_distinct); |
| |
| retval = (Node *) aggref; |
| } |
| else |
| { |
| /* window function */ |
| WindowFunc *wfunc = makeNode(WindowFunc); |
| |
| 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->location = location; |
| |
| wfunc->windistinct = agg_distinct; |
| |
| /* |
| * agg_star is allowed for aggregate functions but distinct isn't |
| * |
| * GPDB: We have implemented this in GPDB, with some limitations. |
| */ |
| if (agg_distinct) |
| { |
| if (fdresult == FUNCDETAIL_WINDOWFUNC) |
| ereport(ERROR, |
| (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| errmsg("DISTINCT is not implemented for window functions"), |
| parser_errposition(pstate, location))); |
| |
| if (list_length(fargs) != 1) |
| ereport(ERROR, |
| (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| errmsg("DISTINCT is supported only for single-argument window aggregates"))); |
| } |
| |
| /* |
| * Reject attempt to call a parameterless aggregate without (*) |
| * syntax. This is mere pedantry but some folks insisted ... |
| * |
| * GPDB: We allow this in GPDB. |
| */ |
| #if 0 |
| 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))); |
| #endif |
| |
| /* |
| * ordered aggs not allowed in windows yet |
| */ |
| 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))); |
| |
| /* |
| * FILTER is not yet supported with true window functions |
| */ |
| 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))); |
| |
| /* |
| * Window functions can't either take or return sets |
| */ |
| 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)))); |
| |
| if (retset) |
| ereport(ERROR, |
| (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
| errmsg("window functions cannot return sets"), |
| parser_errposition(pstate, location))); |
| |
| /* parse_agg.c does additional window-func-specific processing */ |
| transformWindowFuncCall(pstate, wfunc, over); |
| |
| retval = (Node *) wfunc; |
| } |
| |
| /* |
| * Mark the context if this is a dynamic typed function, if so we mustn't |
| * allow views to be created from this statement because we cannot |
| * guarantee that the future return type will be the same as the current |
| * return type. |
| */ |
| if (TypeSupportsDescribe(rettype)) |
| { |
| Oid DescribeFuncOid = lookupProcCallback(funcid, PROMETHOD_DESCRIBE); |
| if (OidIsValid(DescribeFuncOid)) |
| { |
| ParseState *state = pstate; |
| |
| for (state = pstate; state; state = state->parentParseState) |
| state->p_hasDynamicFunction = true; |
| } |
| } |
| |
| /* |
| * If this function has restrictions on where it can be executed |
| * (EXECUTE ON MASTER or EXECUTE ON ALL SEGMENTS), make note of that, |
| * so that the planner knows to be prepared for it. |
| */ |
| if (func_exec_location(funcid) != PROEXECLOCATION_ANY) |
| pstate->p_hasFuncsWithExecRestrictions = true; |
| |
| /* if it returns a set, remember it for error checks at higher levels */ |
| if (retset) |
| pstate->p_last_srf = retval; |
| |
| return retval; |
| } |
| |
| |
| /* func_match_argtypes() |
| * |
| * Given a list of candidate functions (having the right name and number |
| * of arguments) and an array of input datatype OIDs, produce a shortlist of |
| * those candidates that actually accept the input datatypes (either exactly |
| * or by coercion), and return the number of such candidates. |
| * |
| * Note that can_coerce_type will assume that UNKNOWN inputs are coercible to |
| * anything, so candidates will not be eliminated on that basis. |
| * |
| * NB: okay to modify input list structure, as long as we find at least |
| * one match. If no match at all, the list must remain unmodified. |
| */ |
| int |
| func_match_argtypes(int nargs, |
| Oid *input_typeids, |
| FuncCandidateList raw_candidates, |
| FuncCandidateList *candidates) /* return value */ |
| { |
| FuncCandidateList current_candidate; |
| FuncCandidateList next_candidate; |
| int ncandidates = 0; |
| |
| *candidates = NULL; |
| |
| for (current_candidate = raw_candidates; |
| current_candidate != NULL; |
| current_candidate = next_candidate) |
| { |
| next_candidate = current_candidate->next; |
| if (can_coerce_type(nargs, input_typeids, current_candidate->args, |
| COERCION_IMPLICIT)) |
| { |
| current_candidate->next = *candidates; |
| *candidates = current_candidate; |
| ncandidates++; |
| } |
| } |
| |
| return ncandidates; |
| } /* func_match_argtypes() */ |
| |
| |
| /* func_select_candidate() |
| * Given the input argtype array and more than one candidate |
| * for the function, attempt to resolve the conflict. |
| * |
| * Returns the selected candidate if the conflict can be resolved, |
| * otherwise returns NULL. |
| * |
| * Note that the caller has already determined that there is no candidate |
| * exactly matching the input argtypes, and has pruned away any "candidates" |
| * that aren't actually coercion-compatible with the input types. |
| * |
| * This is also used for resolving ambiguous operator references. Formerly |
| * parse_oper.c had its own, essentially duplicate code for the purpose. |
| * The following comments (formerly in parse_oper.c) are kept to record some |
| * of the history of these heuristics. |
| * |
| * OLD COMMENTS: |
| * |
| * This routine is new code, replacing binary_oper_select_candidate() |
| * which dates from v4.2/v1.0.x days. It tries very hard to match up |
| * operators with types, including allowing type coercions if necessary. |
| * The important thing is that the code do as much as possible, |
| * while _never_ doing the wrong thing, where "the wrong thing" would |
| * be returning an operator when other better choices are available, |
| * or returning an operator which is a non-intuitive possibility. |
| * - thomas 1998-05-21 |
| * |
| * The comments below came from binary_oper_select_candidate(), and |
| * illustrate the issues and choices which are possible: |
| * - thomas 1998-05-20 |
| * |
| * current wisdom holds that the default operator should be one in which |
| * both operands have the same type (there will only be one such |
| * operator) |
| * |
| * 7.27.93 - I have decided not to do this; it's too hard to justify, and |
| * it's easy enough to typecast explicitly - avi |
| * [the rest of this routine was commented out since then - ay] |
| * |
| * 6/23/95 - I don't complete agree with avi. In particular, casting |
| * floats is a pain for users. Whatever the rationale behind not doing |
| * this is, I need the following special case to work. |
| * |
| * In the WHERE clause of a query, if a float is specified without |
| * quotes, we treat it as float8. I added the float48* operators so |
| * that we can operate on float4 and float8. But now we have more than |
| * one matching operator if the right arg is unknown (eg. float |
| * specified with quotes). This break some stuff in the regression |
| * test where there are floats in quotes not properly casted. Below is |
| * the solution. In addition to requiring the operator operates on the |
| * same type for both operands [as in the code Avi originally |
| * commented out], we also require that the operators be equivalent in |
| * some sense. (see equivalentOpersAfterPromotion for details.) |
| * - ay 6/95 |
| */ |
| FuncCandidateList |
| func_select_candidate(int nargs, |
| Oid *input_typeids, |
| FuncCandidateList candidates) |
| { |
| FuncCandidateList current_candidate, |
| first_candidate, |
| last_candidate; |
| Oid *current_typeids; |
| Oid current_type; |
| int i; |
| int ncandidates; |
| int nbestMatch, |
| nmatch, |
| nunknowns; |
| Oid input_base_typeids[FUNC_MAX_ARGS]; |
| TYPCATEGORY slot_category[FUNC_MAX_ARGS], |
| current_category; |
| bool current_is_preferred; |
| bool slot_has_preferred_type[FUNC_MAX_ARGS]; |
| bool resolved_unknowns; |
| |
| /* 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))); |
| |
| /* |
| * If any input types are domains, reduce them to their base types. This |
| * ensures that we will consider functions on the base type to be "exact |
| * matches" in the exact-match heuristic; it also makes it possible to do |
| * something useful with the type-category heuristics. Note that this |
| * makes it difficult, but not impossible, to use functions declared to |
| * take a domain as an input datatype. Such a function will be selected |
| * over the base-type function only if it is an exact match at all |
| * argument positions, and so was already chosen by our caller. |
| * |
| * While we're at it, count the number of unknown-type arguments for use |
| * 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++; |
| } |
| } |
| |
| /* |
| * Run through all candidates and keep those with the most matches on |
| * exact types. Keep all candidates if none match. |
| */ |
| 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? */ |
| else if (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; |
| |
| /* |
| * Still too many candidates? Now look for candidates which have either |
| * exact matches or preferred types at the args that will require |
| * coercion. (Restriction added in 7.4: preferred type must be of same |
| * category as input type; give no preference to cross-category |
| * conversions to preferred types.) Keep all candidates if none match. |
| */ |
| 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 ((nmatch > nbestMatch) || (last_candidate == NULL)) |
| { |
| nbestMatch = nmatch; |
| candidates = current_candidate; |
| last_candidate = current_candidate; |
| ncandidates = 1; |
| } |
| else if (nmatch == nbestMatch) |
| { |
| last_candidate->next = current_candidate; |
| last_candidate = current_candidate; |
| ncandidates++; |
| } |
| } |
| |
| if (last_candidate) /* terminate rebuilt list */ |
| last_candidate->next = NULL; |
| |
| if (ncandidates == 1) |
| return candidates; |
| |
| /* |
| * Still too many candidates? Try assigning types for the unknown inputs. |
| * |
| * If there are no unknown inputs, we have no more heuristics that apply, |
| * and must fail. |
| */ |
| if (nunknowns == 0) |
| return NULL; /* failed to select a best candidate */ |
| |
| /* |
| * The next step examines each unknown argument position to see if we can |
| * determine a "type category" for it. If any candidate has an input |
| * datatype of STRING category, use STRING category (this bias towards |
| * STRING is appropriate since unknown-type literals look like strings). |
| * Otherwise, if all the candidates agree on the type category of this |
| * argument position, use that category. Otherwise, fail because we |
| * cannot determine a category. |
| * |
| * If we are able to determine a type category, also notice whether any of |
| * the candidates takes a preferred datatype within the category. |
| * |
| * Having completed this examination, remove candidates that accept the |
| * wrong category at any unknown position. Also, if at least one |
| * candidate accepted a preferred type at a position, remove candidates |
| * that accept non-preferred types. If just one candidate remains, return |
| * that one. However, if this rule turns out to reject all candidates, |
| * keep them all instead. |
| */ |
| resolved_unknowns = false; |
| for (i = 0; i < nargs; i++) |
| { |
| bool have_conflict; |
| |
| if (input_base_typeids[i] != UNKNOWNOID) |
| continue; |
| resolved_unknowns = true; /* assume we can do it */ |
| slot_category[i] = TYPCATEGORY_INVALID; |
| slot_has_preferred_type[i] = false; |
| have_conflict = false; |
| for (current_candidate = candidates; |
| current_candidate != NULL; |
| current_candidate = current_candidate->next) |
| { |
| current_typeids = current_candidate->args; |
| current_type = current_typeids[i]; |
| get_type_category_preferred(current_type, |
| ¤t_category, |
| ¤t_is_preferred); |
| if (slot_category[i] == TYPCATEGORY_INVALID) |
| { |
| /* first candidate */ |
| slot_category[i] = current_category; |
| slot_has_preferred_type[i] = current_is_preferred; |
| } |
| else if (current_category == slot_category[i]) |
| { |
| /* more candidates in same category */ |
| slot_has_preferred_type[i] |= current_is_preferred; |
| } |
| else |
| { |
| /* category conflict! */ |
| if (current_category == TYPCATEGORY_STRING) |
| { |
| /* STRING always wins if available */ |
| slot_category[i] = current_category; |
| slot_has_preferred_type[i] = current_is_preferred; |
| } |
| else |
| { |
| /* |
| * Remember conflict, but keep going (might find STRING) |
| */ |
| have_conflict = true; |
| } |
| } |
| } |
| if (have_conflict && slot_category[i] != TYPCATEGORY_STRING) |
| { |
| /* Failed to resolve category conflict at this position */ |
| resolved_unknowns = false; |
| break; |
| } |
| } |
| |
| if (resolved_unknowns) |
| { |
| /* Strip non-matching candidates */ |
| ncandidates = 0; |
| first_candidate = candidates; |
| last_candidate = NULL; |
| for (current_candidate = candidates; |
| current_candidate != NULL; |
| current_candidate = current_candidate->next) |
| { |
| bool keepit = true; |
| |
| 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; |
| } |
| |
| /* |
| * Last gasp: if there are both known- and unknown-type inputs, and all |
| * the known types are the same, assume the unknown inputs are also that |
| * type, and see if that gives us a unique match. If so, use that match. |
| * |
| * NOTE: for a binary operator with one unknown and one non-unknown input, |
| * we already tried this heuristic in binary_oper_exact(). However, that |
| * code only finds exact matches, whereas here we will handle matches that |
| * involve coercion, polymorphic type resolution, 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]; |
| else if (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() |
| * |
| * Find the named function in the system catalogs. |
| * |
| * Attempt to find the named function in the system catalogs with |
| * arguments exactly as specified, so that the normal case (exact match) |
| * is as quick as possible. |
| * |
| * If an exact match isn't found: |
| * 1) check for possible interpretation as a type coercion request |
| * 2) apply the ambiguous-function resolution rules |
| * |
| * 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), |
| * the returned true_typeids and argdefaults are ordered according to the |
| * call's argument ordering: first any positional arguments, then the named |
| * arguments, then defaulted arguments (if needed and allowed by |
| * expand_defaults). Some care is needed if this information is to be compared |
| * to the function's pg_proc entry, but in practice the caller can usually |
| * just work with the call's argument ordering. |
| * |
| * We rely primarily on fargnames/nargs/argtypes as the argument description. |
| * The actual expression node list is passed in fargs so that we can check |
| * for type coercion of a constant. Some callers pass fargs == NIL indicating |
| * they don't need that check made. Note also that when fargnames isn't NIL, |
| * the fargs list must be passed if the caller wants actual argument position |
| * information to be returned into the NamedArgExpr nodes. |
| */ |
| 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; |
| |
| /* initialize output arguments to silence compiler warnings */ |
| *funcid = InvalidOid; |
| *rettype = InvalidOid; |
| *retset = false; |
| *nvargs = 0; |
| *vatype = InvalidOid; |
| *true_typeids = NULL; |
| if (argdefaults) |
| *argdefaults = NIL; |
| |
| /* Get list of possible candidates from namespace search */ |
| raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames, |
| expand_variadic, expand_defaults, |
| include_out_arguments, false); |
| |
| /* |
| * Quickly check if there is an exact match to the input datatypes (there |
| * can be only one) |
| */ |
| 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; |
| } |
| |
| if (best_candidate == NULL) |
| { |
| /* |
| * If we didn't find an exact match, next consider the possibility |
| * that this is really a type-coercion request: a single-argument |
| * function call where the function name is a type name. If so, and |
| * if the coercion path is RELABELTYPE or COERCEVIAIO, then go ahead |
| * and treat the "function call" as a coercion. |
| * |
| * This interpretation needs to be given higher priority than |
| * interpretations involving a type coercion followed by a function |
| * call, otherwise we can produce surprising results. For example, we |
| * want "text(varchar)" to be interpreted as a simple coercion, not as |
| * "text(name(varchar))" which the code below this point is entirely |
| * capable of selecting. |
| * |
| * We also treat a coercion of a previously-unknown-type literal |
| * constant to a specific type this way. |
| * |
| * The reason we reject COERCION_PATH_FUNC here is that we expect the |
| * cast implementation function to be named after the target type. |
| * Thus the function will be found by normal lookup if appropriate. |
| * |
| * The reason we reject COERCION_PATH_ARRAYCOERCE is mainly that you |
| * can't write "foo[] (something)" as a function call. In theory |
| * someone might want to invoke it as "_foo (something)" but we have |
| * never supported that historically, so we can insist that people |
| * write it as a normal cast instead. |
| * |
| * We also reject the specific case of COERCEVIAIO for a composite |
| * source type and a string-category target type. This is a case that |
| * find_coercion_pathway() allows by default, but experience has shown |
| * that it's too commonly invoked by mistake. So, again, insist that |
| * people use cast syntax if they want to do that. |
| * |
| * NB: it's important that this code does not exceed what coerce_type |
| * can do, because the caller will try to apply coerce_type if we |
| * return FUNCDETAIL_COERCION. If we return that result for something |
| * coerce_type can't handle, we'll cause infinite recursion between |
| * this module and coerce_type! |
| */ |
| if (nargs == 1 && fargs != NIL && fargnames == NIL) |
| { |
| Oid targetType = FuncNameAsType(funcname); |
| |
| if (OidIsValid(targetType)) |
| { |
| Oid sourceType = argtypes[0]; |
| Node *arg1 = linitial(fargs); |
| bool iscoercion; |
| |
| if (sourceType == UNKNOWNOID && IsA(arg1, Const)) |
| { |
| /* always treat typename('literal') as coercion */ |
| iscoercion = true; |
| } |
| else |
| { |
| CoercionPathType cpathtype; |
| Oid cfuncid; |
| |
| cpathtype = find_coercion_pathway(targetType, sourceType, |
| COERCION_EXPLICIT, |
| &cfuncid); |
| switch (cpathtype) |
| { |
| case COERCION_PATH_RELABELTYPE: |
| iscoercion = true; |
| break; |
| case COERCION_PATH_COERCEVIAIO: |
| if ((sourceType == RECORDOID || |
| ISCOMPLEX(sourceType)) && |
| TypeCategory(targetType) == TYPCATEGORY_STRING) |
| iscoercion = false; |
| else |
| iscoercion = true; |
| break; |
| default: |
| iscoercion = false; |
| break; |
| } |
| } |
| |
| if (iscoercion) |
| { |
| /* Treat it as a type coercion */ |
| *funcid = InvalidOid; |
| *rettype = targetType; |
| *retset = false; |
| *nvargs = 0; |
| *vatype = InvalidOid; |
| *true_typeids = argtypes; |
| return FUNCDETAIL_COERCION; |
| } |
| } |
| } |
| |
| /* |
| * didn't find an exact match, so now try to match up candidates... |
| */ |
| if (raw_candidates != NULL) |
| { |
| FuncCandidateList current_candidates; |
| int ncandidates; |
| |
| ncandidates = func_match_argtypes(nargs, |
| argtypes, |
| raw_candidates, |
| ¤t_candidates); |
| |
| /* one match only? then run with it... */ |
| if (ncandidates == 1) |
| best_candidate = current_candidates; |
| |
| /* |
| * multiple candidates? then better decide or throw an error... |
| */ |
| else if (ncandidates > 1) |
| { |
| best_candidate = func_select_candidate(nargs, |
| argtypes, |
| current_candidates); |
| |
| /* |
| * If we were able to choose a best candidate, we're done. |
| * Otherwise, ambiguous function call. |
| */ |
| if (!best_candidate) |
| return FUNCDETAIL_MULTIPLE; |
| } |
| } |
| } |
| |
| if (best_candidate) |
| { |
| HeapTuple ftup; |
| Form_pg_proc pform; |
| FuncDetailCode result; |
| |
| /* |
| * If processing named args or expanding variadics or defaults, the |
| * "best candidate" might represent multiple equivalently good |
| * functions; treat this case as ambiguous. |
| */ |
| if (!OidIsValid(best_candidate->oid)) |
| return FUNCDETAIL_MULTIPLE; |
| |
| /* |
| * We disallow VARIADIC with named arguments unless the last argument |
| * (the one with VARIADIC attached) actually matched the variadic |
| * parameter. This is mere pedantry, really, but some folks insisted. |
| */ |
| if (fargnames != NIL && !expand_variadic && nargs > 0 && |
| best_candidate->argnumbers[nargs - 1] != nargs - 1) |
| return FUNCDETAIL_NOTFOUND; |
| |
| *funcid = best_candidate->oid; |
| *nvargs = best_candidate->nvargs; |
| *true_typeids = best_candidate->args; |
| |
| /* |
| * If processing named args, return actual argument positions into |
| * NamedArgExpr nodes in the fargs list. This is a bit ugly but not |
| * worth the extra notation needed to do it differently. |
| */ |
| if (best_candidate->argnumbers != NULL) |
| { |
| int i = 0; |
| ListCell *lc; |
| |
| foreach(lc, fargs) |
| { |
| NamedArgExpr *na = (NamedArgExpr *) lfirst(lc); |
| |
| if (IsA(na, NamedArgExpr)) |
| na->argnumber = best_candidate->argnumbers[i]; |
| i++; |
| } |
| } |
| |
| ftup = SearchSysCache1(PROCOID, |
| ObjectIdGetDatum(best_candidate->oid)); |
| if (!HeapTupleIsValid(ftup)) /* should not happen */ |
| elog(ERROR, "cache lookup failed for function %u", |
| best_candidate->oid); |
| pform = (Form_pg_proc) GETSTRUCT(ftup); |
| *rettype = pform->prorettype; |
| *retset = pform->proretset; |
| *vatype = pform->provariadic; |
| /* fetch default args if caller wants 'em */ |
| if (argdefaults && best_candidate->ndargs > 0) |
| { |
| Datum proargdefaults; |
| char *str; |
| List *defaults; |
| |
| /* shouldn't happen, FuncnameGetCandidates messed up */ |
| if (best_candidate->ndargs > pform->pronargdefaults) |
| elog(ERROR, "not enough default arguments"); |
| |
| proargdefaults = SysCacheGetAttrNotNull(PROCOID, ftup, |
| Anum_pg_proc_proargdefaults); |
| str = TextDatumGetCString(proargdefaults); |
| defaults = castNode(List, stringToNode(str)); |
| pfree(str); |
| |
| /* Delete any unused defaults from the returned list */ |
| if (best_candidate->argnumbers != NULL) |
| { |
| /* |
| * This is a bit tricky in named notation, since the supplied |
| * arguments could replace any subset of the defaults. We |
| * work by making a bitmapset of the argnumbers of defaulted |
| * arguments, then scanning the defaults list and selecting |
| * the needed items. (This assumes that defaulted arguments |
| * should be supplied in their positional order.) |
| */ |
| 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 |
| { |
| /* |
| * Defaults for positional notation are lots easier; just |
| * remove any unwanted ones from the front. |
| */ |
| int ndelete; |
| |
| ndelete = list_length(defaults) - best_candidate->ndargs; |
| if (ndelete > 0) |
| defaults = list_delete_first_n(defaults, ndelete); |
| *argdefaults = defaults; |
| } |
| } |
| |
| 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() |
| * |
| * Ensure that each hypothetical direct argument of a hypothetical-set |
| * aggregate has the same type as the corresponding aggregated argument. |
| * Modify the expressions in the fargs list, if necessary, and update |
| * actual_arg_types[]. |
| * |
| * If the agg declared its args non-ANY (even ANYELEMENT), we need only a |
| * sanity check that the declared types match; make_fn_arguments will coerce |
| * the actual arguments to match the declared ones. But if the declaration |
| * is ANY, nothing will happen in make_fn_arguments, so we need to fix any |
| * mismatch here. We use the same type resolution logic as UNION etc. |
| */ |
| static void |
| 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; |
| |
| /* |
| * Select common type, giving preference to the aggregated argument's |
| * type (we'd rather coerce the direct argument once than coerce all |
| * the aggregated values). |
| */ |
| commontype = select_common_type(pstate, |
| list_make2(lfirst(aarg), lfirst(harg)), |
| "WITHIN GROUP", |
| NULL); |
| commontypmod = select_common_typmod(pstate, |
| list_make2(lfirst(aarg), lfirst(harg)), |
| commontype); |
| |
| /* |
| * Perform the coercions. We don't need to worry about NamedArgExprs |
| * here because they aren't supported with aggregates. |
| */ |
| lfirst(harg) = coerce_type(pstate, |
| (Node *) lfirst(harg), |
| actual_arg_types[hargpos], |
| commontype, commontypmod, |
| COERCION_IMPLICIT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| actual_arg_types[hargpos] = commontype; |
| lfirst(aarg) = coerce_type(pstate, |
| (Node *) lfirst(aarg), |
| actual_arg_types[aargpos], |
| commontype, commontypmod, |
| COERCION_IMPLICIT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| actual_arg_types[aargpos] = commontype; |
| } |
| } |
| |
| |
| /* |
| * make_fn_arguments() |
| * |
| * Given the actual argument expressions for a function, and the desired |
| * input types for the function, add any necessary typecasting to the |
| * expression tree. Caller should already have verified that casting is |
| * allowed. |
| * |
| * Caution: given argument list is modified in-place. |
| * |
| * As with coerce_type, pstate may be NULL if no special unknown-Param |
| * processing is wanted. |
| */ |
| 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); |
| |
| /* |
| * If arg is a NamedArgExpr, coerce its input expr instead --- we |
| * want the NamedArgExpr to stay at the top level of the list. |
| */ |
| if (IsA(node, NamedArgExpr)) |
| { |
| NamedArgExpr *na = (NamedArgExpr *) node; |
| |
| node = coerce_type(pstate, |
| (Node *) na->arg, |
| actual_arg_types[i], |
| declared_arg_types[i], -1, |
| COERCION_IMPLICIT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| na->arg = (Expr *) node; |
| } |
| else |
| { |
| node = coerce_type(pstate, |
| node, |
| actual_arg_types[i], |
| declared_arg_types[i], -1, |
| COERCION_IMPLICIT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| lfirst(current_fargs) = node; |
| } |
| } |
| i++; |
| } |
| } |
| |
| /* |
| * FuncNameAsType - |
| * convenience routine to see if a function name matches a type name |
| * |
| * Returns the OID of the matching type, or InvalidOid if none. We ignore |
| * shell types and complex types. |
| */ |
| static Oid |
| FuncNameAsType(List *funcname) |
| { |
| Oid result; |
| Type typtup; |
| |
| /* |
| * temp_ok=false protects the <refsect1 id="sql-createfunction-security"> |
| * contract for writing SECURITY DEFINER functions safely. |
| */ |
| typtup = LookupTypeNameExtended(NULL, makeTypeNameFromNameList(funcname), |
| NULL, false, false); |
| if (typtup == NULL) |
| return InvalidOid; |
| |
| if (((Form_pg_type) GETSTRUCT(typtup))->typisdefined && |
| !OidIsValid(typeTypeRelid(typtup))) |
| result = typeTypeId(typtup); |
| else |
| result = InvalidOid; |
| |
| ReleaseSysCache(typtup); |
| return result; |
| } |
| |
| /* |
| * ParseComplexProjection - |
| * handles function calls with a single argument that is of complex type. |
| * If the function call is actually a column projection, return a suitably |
| * transformed expression tree. If not, return NULL. |
| */ |
| static Node * |
| ParseComplexProjection(ParseState *pstate, const char *funcname, Node *first_arg, |
| int location) |
| { |
| TupleDesc tupdesc; |
| int i; |
| |
| /* |
| * Special case for whole-row Vars so that we can resolve (foo.*).bar even |
| * when foo is a reference to a subselect, join, or RECORD function. A |
| * bonus is that we avoid generating an unnecessary FieldSelect; our |
| * result can omit the whole-row Var and just be a Var for the selected |
| * field. |
| * |
| * This case could be handled by expandRecordVariable, but it's more |
| * efficient to do it this way when possible. |
| */ |
| if (IsA(first_arg, Var) && |
| ((Var *) first_arg)->varattno == InvalidAttrNumber) |
| { |
| ParseNamespaceItem *nsitem; |
| |
| nsitem = GetNSItemByRangeTablePosn(pstate, |
| ((Var *) first_arg)->varno, |
| ((Var *) first_arg)->varlevelsup); |
| /* Return a Var if funcname matches a column, else NULL */ |
| return scanNSItemForColumn(pstate, nsitem, |
| ((Var *) first_arg)->varlevelsup, |
| funcname, location); |
| } |
| |
| /* |
| * Else do it the hard way with get_expr_result_tupdesc(). |
| * |
| * If it's a Var of type RECORD, we have to work even harder: we have to |
| * find what the Var refers to, and pass that to get_expr_result_tupdesc. |
| * That task is handled by expandRecordVariable(). |
| */ |
| if (IsA(first_arg, Var) && |
| ((Var *) first_arg)->vartype == RECORDOID) |
| tupdesc = expandRecordVariable(pstate, (Var *) first_arg, 0); |
| else |
| tupdesc = get_expr_result_tupdesc(first_arg, true); |
| if (!tupdesc) |
| return NULL; /* unresolvable RECORD type */ |
| |
| for (i = 0; i < tupdesc->natts; i++) |
| { |
| Form_pg_attribute att = TupleDescAttr(tupdesc, i); |
| |
| if (strcmp(funcname, NameStr(att->attname)) == 0 && |
| !att->attisdropped) |
| { |
| /* Success, so generate a FieldSelect expression */ |
| FieldSelect *fselect = makeNode(FieldSelect); |
| |
| fselect->arg = (Expr *) first_arg; |
| fselect->fieldnum = i + 1; |
| fselect->resulttype = att->atttypid; |
| fselect->resulttypmod = att->atttypmod; |
| /* save attribute's collation for parse_collate.c */ |
| fselect->resultcollid = att->attcollation; |
| return (Node *) fselect; |
| } |
| } |
| |
| return NULL; /* funcname does not match any column */ |
| } |
| |
| /* |
| * funcname_signature_string |
| * Build a string representing a function name, including arg types. |
| * The result is something like "foo(integer)". |
| * |
| * If argnames isn't NIL, it is a list of C strings representing the actual |
| * arg names for the last N arguments. This must be considered part of the |
| * function signature too, when dealing with named-notation function calls. |
| * |
| * This is typically used in the construction of function-not-found error |
| * messages. |
| */ |
| const char * |
| funcname_signature_string(const char *funcname, int nargs, |
| List *argnames, const Oid *argtypes) |
| { |
| StringInfoData argbuf; |
| int numposargs; |
| ListCell *lc; |
| int i; |
| |
| initStringInfo(&argbuf); |
| |
| appendStringInfo(&argbuf, "%s(", funcname); |
| |
| numposargs = nargs - list_length(argnames); |
| lc = list_head(argnames); |
| |
| for (i = 0; i < nargs; i++) |
| { |
| if (i) |
| appendStringInfoString(&argbuf, ", "); |
| if (i >= numposargs) |
| { |
| appendStringInfo(&argbuf, "%s => ", (char *) lfirst(lc)); |
| lc = lnext(argnames, lc); |
| } |
| appendStringInfoString(&argbuf, format_type_be(argtypes[i])); |
| } |
| |
| appendStringInfoChar(&argbuf, ')'); |
| |
| return argbuf.data; /* return palloc'd string buffer */ |
| } |
| |
| /* |
| * func_signature_string |
| * As above, but function name is passed as a qualified name list. |
| */ |
| const char * |
| func_signature_string(List *funcname, int nargs, |
| List *argnames, const Oid *argtypes) |
| { |
| return funcname_signature_string(NameListToString(funcname), |
| nargs, argnames, argtypes); |
| } |
| |
| /* |
| * LookupFuncNameInternal |
| * Workhorse for LookupFuncName/LookupFuncWithArgs |
| * |
| * In an error situation, e.g. can't find the function, then we return |
| * InvalidOid and set *lookupError to indicate what went wrong. |
| * |
| * Possible errors: |
| * FUNCLOOKUP_NOSUCHFUNC: we can't find a function of this name. |
| * FUNCLOOKUP_AMBIGUOUS: more than one function matches. |
| */ |
| 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 |
| * |
| * Given a possibly-qualified function name and optionally a set of argument |
| * types, look up the function. Pass nargs == -1 to indicate that the number |
| * and types of the arguments are unspecified (this is NOT the same as |
| * specifying that there are no arguments). |
| * |
| * If the function name is not schema-qualified, it is sought in the current |
| * namespace search path. |
| * |
| * If the function is not found, we return InvalidOid if missing_ok is true, |
| * else raise an error. |
| * |
| * If nargs == -1 and multiple functions are found matching this function name |
| * we will raise an ambiguous-function error, regardless of what missing_ok is |
| * set to. |
| * |
| * Only functions will be found; procedures will be ignored even if they |
| * match the name and argument types. (However, we don't trouble to reject |
| * aggregates or window functions here.) |
| */ |
| Oid |
| LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok) |
| { |
| Oid funcoid; |
| FuncLookupError lookupError; |
| |
| funcoid = LookupFuncNameInternal(OBJECT_FUNCTION, |
| funcname, nargs, argtypes, |
| false, missing_ok, |
| &lookupError); |
| |
| if (OidIsValid(funcoid)) |
| return funcoid; |
| |
| 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 |
| * |
| * Like LookupFuncName, but the argument types are specified by an |
| * ObjectWithArgs node. Also, this function can check whether the result is a |
| * function, procedure, or aggregate, based on the objtype argument. Pass |
| * OBJECT_ROUTINE to accept any of them. |
| * |
| * For historical reasons, we also accept aggregates when looking for a |
| * function. |
| * |
| * When missing_ok is true we don't generate any error for missing objects and |
| * return InvalidOid. Other types of errors can still be raised, regardless |
| * of the value of missing_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; |
| |
| Assert(objtype == OBJECT_AGGREGATE || |
| objtype == OBJECT_FUNCTION || |
| objtype == OBJECT_PROCEDURE || |
| objtype == OBJECT_ROUTINE); |
| |
| 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))); |
| } |
| |
| /* |
| * First, perform a lookup considering only input arguments (traditional |
| * Postgres rules). |
| */ |
| i = 0; |
| foreach(args_item, func->objargs) |
| { |
| TypeName *t = lfirst_node(TypeName, args_item); |
| |
| argoids[i] = LookupTypeNameOid(NULL, t, missing_ok); |
| if (!OidIsValid(argoids[i])) |
| return InvalidOid; /* missing_ok must be true */ |
| i++; |
| } |
| |
| /* |
| * Set nargs for LookupFuncNameInternal. It expects -1 to mean no args |
| * were specified. |
| */ |
| nargs = func->args_unspecified ? -1 : argcount; |
| |
| /* |
| * In args_unspecified mode, also tell LookupFuncNameInternal to consider |
| * the object type, since there seems no reason not to. However, if we |
| * have an argument list, disable the objtype check, because we'd rather |
| * complain about "object is of wrong type" than "object doesn't exist". |
| * (Note that with args, FuncnameGetCandidates will have ensured there's |
| * only one argtype match, so we're not risking an ambiguity failure via |
| * this choice.) |
| */ |
| oid = LookupFuncNameInternal(func->args_unspecified ? objtype : OBJECT_ROUTINE, |
| func->objname, nargs, argoids, |
| false, missing_ok, |
| &lookupError); |
| |
| /* |
| * If PROCEDURE or ROUTINE was specified, and we have an argument list |
| * that contains no parameter mode markers, and we didn't already discover |
| * that there's ambiguity, perform a lookup considering all arguments. |
| * (Note: for a zero-argument procedure, or in args_unspecified mode, the |
| * normal lookup is sufficient; so it's OK to require non-NIL objfuncargs |
| * to perform this lookup.) |
| */ |
| if ((objtype == OBJECT_PROCEDURE || objtype == OBJECT_ROUTINE) && |
| func->objfuncargs != NIL && |
| lookupError != FUNCLOOKUP_AMBIGUOUS) |
| { |
| bool have_param_mode = false; |
| |
| /* |
| * Check for non-default parameter mode markers. If there are any, |
| * then the command does not conform to SQL-spec syntax, so we may |
| * assume that the traditional Postgres lookup method of considering |
| * only input parameters is sufficient. (Note that because the spec |
| * doesn't have OUT arguments for functions, we also don't need this |
| * hack in FUNCTION or AGGREGATE mode.) |
| */ |
| foreach(args_item, func->objfuncargs) |
| { |
| FunctionParameter *fp = lfirst_node(FunctionParameter, args_item); |
| |
| if (fp->mode != FUNC_PARAM_DEFAULT) |
| { |
| have_param_mode = true; |
| break; |
| } |
| } |
| |
| if (!have_param_mode) |
| { |
| Oid poid; |
| |
| /* 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; |
| } |
| else if (lookupError == FUNCLOOKUP_AMBIGUOUS) |
| oid = InvalidOid; |
| } |
| } |
| |
| if (OidIsValid(oid)) |
| { |
| /* |
| * Even if we found the function, perform validation that the objtype |
| * matches the prokind of the found function. For historical reasons |
| * we allow the objtype of FUNCTION to include aggregates and window |
| * functions; but we draw the line if the object is a procedure. That |
| * is a new enough feature that this historical rule does not apply. |
| * |
| * (This check is partially redundant with the objtype check in |
| * LookupFuncNameInternal; but not entirely, since we often don't tell |
| * LookupFuncNameInternal to apply that check at all.) |
| */ |
| 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; |
| |
| default: |
| /* OBJECT_ROUTINE accepts anything. */ |
| 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)))); |
| else if (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; |
| |
| default: |
| Assert(false); /* Disallowed by Assert above */ |
| break; |
| } |
| break; |
| } |
| |
| return InvalidOid; |
| } |
| } |
| |
| /* |
| * check_srf_call_placement |
| * Verify that a set-returning function is called in a valid place, |
| * and throw a nice error if not. |
| * |
| * A side-effect is to set pstate->p_hasTargetSRFs true if appropriate. |
| * |
| * last_srf should be a copy of pstate->p_last_srf from just before we |
| * started transforming the function's arguments. This allows detection |
| * of whether the SRF's arguments contain any SRFs. |
| */ |
| void |
| check_srf_call_placement(ParseState *pstate, Node *last_srf, int location) |
| { |
| const char *err; |
| bool errkind; |
| |
| /* |
| * Check to see if the set-returning function is in an invalid place |
| * within the query. Basically, we don't allow SRFs anywhere except in |
| * the targetlist (which includes GROUP BY/ORDER BY expressions), VALUES, |
| * and functions in FROM. |
| * |
| * For brevity we support two schemes for reporting an error here: set |
| * "err" to a custom message, or set "errkind" true if the error context |
| * is sufficiently identified by what ParseExprKindName will return, *and* |
| * what it will return is just a SQL keyword. (Otherwise, use a custom |
| * message to avoid creating translation problems.) |
| */ |
| 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: |
| 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; |
| |
| case EXPR_KIND_SCATTER_BY: |
| err = _("set-returning functions are not allowed in scatter by expressions"); |
| break; |
| |
| /* |
| * There is intentionally no default: case here, so that the |
| * compiler will warn if we add a new ParseExprKind without |
| * extending this switch. If we do see an unrecognized value at |
| * runtime, the behavior will be the same as for EXPR_KIND_OTHER, |
| * which is sane anyway. |
| */ |
| } |
| 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))); |
| } |
| |
| |
| /* |
| * parseCheckTableFunctions |
| * |
| * Check for TableValueExpr where they shouldn't be. Currently the only |
| * valid location for a TableValueExpr is within a call to a table function. |
| * In the full SQL Standard they can exist anywhere a multiset is supported. |
| */ |
| void |
| parseCheckTableFunctions(ParseState *pstate, Query *qry) |
| { |
| check_table_func_context context; |
| context.parent = NULL; |
| query_tree_walker(qry, |
| checkTableFunctions_walker, |
| (void *) &context, 0); |
| } |
| |
| static bool |
| checkTableFunctions_walker(Node *node, check_table_func_context *context) |
| { |
| if (node == NULL) |
| return false; |
| |
| /* |
| * TABLE() value expressions are currently only permitted as parameters |
| * to table functions called in the FROM clause. |
| */ |
| if (IsA(node, TableValueExpr)) |
| { |
| if (context->parent && IsA(context->parent, FuncExpr)) |
| { |
| FuncExpr *parent = (FuncExpr *) context->parent; |
| |
| /* |
| * This flag is set in addRangeTableEntryForFunction for functions |
| * called as range table entries having TABLE value expressions |
| * as arguments. |
| */ |
| if (parent->is_tablefunc) |
| return false; |
| |
| /* Error message could be improved */ |
| ereport(ERROR, |
| (errcode(ERRCODE_SYNTAX_ERROR), |
| errmsg("table functions must be invoked in FROM clause"))); |
| } |
| ereport(ERROR, |
| (errcode(ERRCODE_SYNTAX_ERROR), |
| errmsg("invalid use of TABLE value expression"))); |
| return true; /* not possible, but keeps compiler happy */ |
| } |
| |
| context->parent = node; |
| if (IsA(node, Query)) |
| { |
| return query_tree_walker((Query *) node, |
| checkTableFunctions_walker, |
| (void *) context, 0); |
| } |
| else |
| { |
| return expression_tree_walker(node, |
| checkTableFunctions_walker, |
| (void *) context); |
| } |
| } |