* evaluate_function: try to pre-evaluate a function call * * We can do this if the function is strict and has any constant-null inputs * (just return a null constant), or if the function is immutable and has all * constant inputs (call it and return the result as a Const node). In * estimation mode we are willing to pre-evaluate stable functions too. * * Returns a simplified expression if
| 4487 | * simplify the function. |
| 4488 | */ |
| 4489 | static Expr * |
| 4490 | evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, |
| 4491 | Oid result_collid, Oid input_collid, List *args, |
| 4492 | bool funcvariadic, |
| 4493 | HeapTuple func_tuple, |
| 4494 | eval_const_expressions_context *context) |
| 4495 | { |
| 4496 | Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple); |
| 4497 | bool has_nonconst_input = false; |
| 4498 | bool has_null_input = false; |
| 4499 | ListCell *arg; |
| 4500 | FuncExpr *newexpr; |
| 4501 | |
| 4502 | /* |
| 4503 | * Can't simplify if it returns a set. |
| 4504 | */ |
| 4505 | if (funcform->proretset) |
| 4506 | return NULL; |
| 4507 | |
| 4508 | /* |
| 4509 | * Can't simplify if it returns RECORD. The immediate problem is that it |
| 4510 | * will be needing an expected tupdesc which we can't supply here. |
| 4511 | * |
| 4512 | * In the case where it has OUT parameters, it could get by without an |
| 4513 | * expected tupdesc, but we still have issues: get_expr_result_type() |
| 4514 | * doesn't know how to extract type info from a RECORD constant, and in |
| 4515 | * the case of a NULL function result there doesn't seem to be any clean |
| 4516 | * way to fix that. In view of the likelihood of there being still other |
| 4517 | * gotchas, seems best to leave the function call unreduced. |
| 4518 | */ |
| 4519 | if (funcform->prorettype == RECORDOID) |
| 4520 | return NULL; |
| 4521 | |
| 4522 | /* |
| 4523 | * Check for constant inputs and especially constant-NULL inputs. |
| 4524 | */ |
| 4525 | foreach(arg, args) |
| 4526 | { |
| 4527 | if (IsA(lfirst(arg), Const)) |
| 4528 | has_null_input |= ((Const *) lfirst(arg))->constisnull; |
| 4529 | else |
| 4530 | has_nonconst_input = true; |
| 4531 | } |
| 4532 | |
| 4533 | /* |
| 4534 | * If the function is strict and has a constant-NULL input, it will never |
| 4535 | * be called at all, so we can replace the call by a NULL constant, even |
| 4536 | * if there are other inputs that aren't constant, and even if the |
| 4537 | * function is not otherwise immutable. |
| 4538 | */ |
| 4539 | if (funcform->proisstrict && has_null_input) |
| 4540 | return (Expr *) makeNullConst(result_type, result_typmod, |
| 4541 | result_collid); |
| 4542 | |
| 4543 | /* |
| 4544 | * Otherwise, can simplify only if all inputs are constants. (For a |
| 4545 | * non-strict function, constant NULL inputs are treated the same as |
| 4546 | * constant non-NULL inputs.) |
no test coverage detected