* evaluate_expr: pre-evaluate a constant expression * * We use the executor's routine ExecEvalExpr() to avoid duplication of * code and ensure we get the same result as the executor would get. */
| 5045 | * code and ensure we get the same result as the executor would get. |
| 5046 | */ |
| 5047 | Expr * |
| 5048 | evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, |
| 5049 | Oid result_collation) |
| 5050 | { |
| 5051 | EState *estate; |
| 5052 | ExprState *exprstate; |
| 5053 | MemoryContext oldcontext; |
| 5054 | Datum const_val; |
| 5055 | bool const_is_null; |
| 5056 | int16 resultTypLen; |
| 5057 | bool resultTypByVal; |
| 5058 | |
| 5059 | /* |
| 5060 | * To use the executor, we need an EState. |
| 5061 | */ |
| 5062 | estate = CreateExecutorState(); |
| 5063 | |
| 5064 | /* We can use the estate's working context to avoid memory leaks. */ |
| 5065 | oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); |
| 5066 | |
| 5067 | /* Make sure any opfuncids are filled in. */ |
| 5068 | fix_opfuncids((Node *) expr); |
| 5069 | |
| 5070 | /* |
| 5071 | * Prepare expr for execution. (Note: we can't use ExecPrepareExpr |
| 5072 | * because it'd result in recursively invoking eval_const_expressions.) |
| 5073 | */ |
| 5074 | exprstate = ExecInitExpr(expr, NULL); |
| 5075 | |
| 5076 | /* |
| 5077 | * And evaluate it. |
| 5078 | * |
| 5079 | * It is OK to use a default econtext because none of the ExecEvalExpr() |
| 5080 | * code used in this situation will use econtext. That might seem |
| 5081 | * fortuitous, but it's not so unreasonable --- a constant expression does |
| 5082 | * not depend on context, by definition, n'est ce pas? |
| 5083 | */ |
| 5084 | const_val = ExecEvalExprSwitchContext(exprstate, |
| 5085 | GetPerTupleExprContext(estate), |
| 5086 | &const_is_null); |
| 5087 | |
| 5088 | /* Get info needed about result datatype */ |
| 5089 | get_typlenbyval(result_type, &resultTypLen, &resultTypByVal); |
| 5090 | |
| 5091 | /* Get back to outer memory context */ |
| 5092 | MemoryContextSwitchTo(oldcontext); |
| 5093 | |
| 5094 | /* |
| 5095 | * Must copy result out of sub-context used by expression eval. |
| 5096 | * |
| 5097 | * Also, if it's varlena, forcibly detoast it. This protects us against |
| 5098 | * storing TOAST pointers into plans that might outlive the referenced |
| 5099 | * data. (makeConst would handle detoasting anyway, but it's worth a few |
| 5100 | * extra lines here so that we can do the copy and detoast in one step.) |
| 5101 | */ |
| 5102 | if (!const_is_null) |
| 5103 | { |
| 5104 | if (resultTypLen == -1) |
no test coverage detected