* Subroutine for eval_const_expressions: try to simplify a function call * (which might originally have been an operator; we don't care) * * Inputs are the function OID, actual result type OID (which is needed for * polymorphic functions), result typmod, result collation, the input * collation to use for the function, the original argument list (not * const-simplified yet, unless process_arg
| 4087 | * possible. |
| 4088 | */ |
| 4089 | static Expr * |
| 4090 | simplify_function(Oid funcid, Oid result_type, int32 result_typmod, |
| 4091 | Oid result_collid, Oid input_collid, List **args_p, |
| 4092 | bool funcvariadic, bool process_args, bool allow_non_const, |
| 4093 | eval_const_expressions_context *context) |
| 4094 | { |
| 4095 | List *args = *args_p; |
| 4096 | HeapTuple func_tuple; |
| 4097 | Form_pg_proc func_form; |
| 4098 | Expr *newexpr; |
| 4099 | |
| 4100 | /* |
| 4101 | * We have three strategies for simplification: execute the function to |
| 4102 | * deliver a constant result, use a transform function to generate a |
| 4103 | * substitute node tree, or expand in-line the body of the function |
| 4104 | * definition (which only works for simple SQL-language functions, but |
| 4105 | * that is a common case). Each case needs access to the function's |
| 4106 | * pg_proc tuple, so fetch it just once. |
| 4107 | * |
| 4108 | * Note: the allow_non_const flag suppresses both the second and third |
| 4109 | * strategies; so if !allow_non_const, simplify_function can only return a |
| 4110 | * Const or NULL. Argument-list rewriting happens anyway, though. |
| 4111 | */ |
| 4112 | func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); |
| 4113 | if (!HeapTupleIsValid(func_tuple)) |
| 4114 | elog(ERROR, "cache lookup failed for function %u", funcid); |
| 4115 | func_form = (Form_pg_proc) GETSTRUCT(func_tuple); |
| 4116 | |
| 4117 | /* |
| 4118 | * Process the function arguments, unless the caller did it already. |
| 4119 | * |
| 4120 | * Here we must deal with named or defaulted arguments, and then |
| 4121 | * recursively apply eval_const_expressions to the whole argument list. |
| 4122 | */ |
| 4123 | if (process_args) |
| 4124 | { |
| 4125 | args = expand_function_arguments(args, false, result_type, func_tuple); |
| 4126 | args = (List *) expression_tree_mutator((Node *) args, |
| 4127 | eval_const_expressions_mutator, |
| 4128 | (void *) context); |
| 4129 | /* Argument processing done, give it back to the caller */ |
| 4130 | *args_p = args; |
| 4131 | } |
| 4132 | |
| 4133 | /* Now attempt simplification of the function call proper. */ |
| 4134 | |
| 4135 | newexpr = evaluate_function(funcid, result_type, result_typmod, |
| 4136 | result_collid, input_collid, |
| 4137 | args, funcvariadic, |
| 4138 | func_tuple, context); |
| 4139 | |
| 4140 | if (large_const(newexpr, context->max_size)) |
| 4141 | { |
| 4142 | // folded expression prohibitively large |
| 4143 | newexpr = NULL; |
| 4144 | } |
| 4145 | |
| 4146 | if (!newexpr && allow_non_const && OidIsValid(func_form->prosupport)) |
no test coverage detected