* Perform setup necessary for the evaluation of a function-like expression, * appending argument evaluation steps to the steps list in *state, and * setting up *scratch so it is ready to be pushed. * * *scratch is not pushed here, so that callers may override the opcode, * which is useful for function-like cases like DISTINCT. */
| 2545 | * which is useful for function-like cases like DISTINCT. |
| 2546 | */ |
| 2547 | static void |
| 2548 | ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, |
| 2549 | Oid inputcollid, ExprState *state) |
| 2550 | { |
| 2551 | int nargs = list_length(args); |
| 2552 | AclResult aclresult; |
| 2553 | FmgrInfo *flinfo; |
| 2554 | FunctionCallInfo fcinfo; |
| 2555 | int argno; |
| 2556 | ListCell *lc; |
| 2557 | |
| 2558 | /* Check permission to call function */ |
| 2559 | aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE); |
| 2560 | if (aclresult != ACLCHECK_OK) |
| 2561 | aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid)); |
| 2562 | InvokeFunctionExecuteHook(funcid); |
| 2563 | |
| 2564 | /* |
| 2565 | * Safety check on nargs. Under normal circumstances this should never |
| 2566 | * fail, as parser should check sooner. But possibly it might fail if |
| 2567 | * server has been compiled with FUNC_MAX_ARGS smaller than some functions |
| 2568 | * declared in pg_proc? |
| 2569 | */ |
| 2570 | if (nargs > FUNC_MAX_ARGS) |
| 2571 | ereport(ERROR, |
| 2572 | (errcode(ERRCODE_TOO_MANY_ARGUMENTS), |
| 2573 | errmsg_plural("cannot pass more than %d argument to a function", |
| 2574 | "cannot pass more than %d arguments to a function", |
| 2575 | FUNC_MAX_ARGS, |
| 2576 | FUNC_MAX_ARGS))); |
| 2577 | |
| 2578 | /* Allocate function lookup data and parameter workspace for this call */ |
| 2579 | scratch->d.func.finfo = palloc0(sizeof(FmgrInfo)); |
| 2580 | scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs)); |
| 2581 | flinfo = scratch->d.func.finfo; |
| 2582 | fcinfo = scratch->d.func.fcinfo_data; |
| 2583 | |
| 2584 | /* Set up the primary fmgr lookup information */ |
| 2585 | fmgr_info(funcid, flinfo); |
| 2586 | fmgr_info_set_expr((Node *) node, flinfo); |
| 2587 | |
| 2588 | /* Initialize function call parameter structure too */ |
| 2589 | InitFunctionCallInfoData(*fcinfo, flinfo, |
| 2590 | nargs, inputcollid, NULL, NULL); |
| 2591 | |
| 2592 | /* Keep extra copies of this info to save an indirection at runtime */ |
| 2593 | scratch->d.func.fn_addr = flinfo->fn_addr; |
| 2594 | scratch->d.func.nargs = nargs; |
| 2595 | |
| 2596 | /* We only support non-set functions here */ |
| 2597 | if (flinfo->fn_retset) |
| 2598 | ereport(ERROR, |
| 2599 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2600 | errmsg("set-valued function called in context that cannot accept a set"), |
| 2601 | state->parent ? |
| 2602 | executor_errposition(state->parent->state, |
| 2603 | exprLocation((Node *) node)) : 0)); |
| 2604 |
no test coverage detected