3232#include "funcapi.h"
3333#include "miscadmin.h"
3434#include "nodes/makefuncs.h"
35+ #include "nodes/miscnodes.h"
3536#include "nodes/multibitmapset.h"
3637#include "nodes/nodeFuncs.h"
3738#include "nodes/subscripting.h"
@@ -2705,7 +2706,7 @@ estimate_expression_value(PlannerInfo *root, Node *node)
27052706 ((Node *) evaluate_expr((Expr *) (node), \
27062707 exprType((Node *) (node)), \
27072708 exprTypmod((Node *) (node)), \
2708- exprCollation((Node *) (node))))
2709+ exprCollation((Node *) (node)), false ))
27092710
27102711/*
27112712 * Recursive guts of eval_const_expressions/estimate_expression_value
@@ -3741,7 +3742,8 @@ eval_const_expressions_mutator(Node *node,
37413742 return (Node * ) evaluate_expr ((Expr * ) svf ,
37423743 svf -> type ,
37433744 svf -> typmod ,
3744- InvalidOid );
3745+ InvalidOid ,
3746+ false);
37453747 else
37463748 return copyObject ((Node * ) svf );
37473749 }
@@ -5293,7 +5295,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
52935295 newexpr -> location = -1 ;
52945296
52955297 return evaluate_expr ((Expr * ) newexpr , result_type , result_typmod ,
5296- result_collid );
5298+ result_collid , true );
52975299}
52985300
52995301/*
@@ -5747,11 +5749,16 @@ sql_inline_error_callback(void *arg)
57475749 *
57485750 * We use the executor's routine ExecEvalExpr() to avoid duplication of
57495751 * code and ensure we get the same result as the executor would get.
5752+ *
5753+ * 'null_on_error' may be passed as true to have the expression evalulation
5754+ * code attempt to supress ERRORs and save them. This of course requires
5755+ * functions properly errsave/ereturn rather than elog/ereport.
57505756 */
57515757Expr *
57525758evaluate_expr (Expr * expr , Oid result_type , int32 result_typmod ,
5753- Oid result_collation )
5759+ Oid result_collation , bool null_on_error )
57545760{
5761+ ErrorSaveContext escontext = {T_ErrorSaveContext };
57555762 EState * estate ;
57565763 ExprState * exprstate ;
57575764 MemoryContext oldcontext ;
@@ -5775,7 +5782,12 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
57755782 * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
57765783 * because it'd result in recursively invoking eval_const_expressions.)
57775784 */
5778- exprstate = ExecInitExpr (expr , NULL );
5785+ if (null_on_error )
5786+ exprstate = ExecInitExprWithErrorContext (expr ,
5787+ NULL ,
5788+ (fmNodePtr * ) & escontext );
5789+ else
5790+ exprstate = ExecInitExpr (expr , NULL );
57795791
57805792 /*
57815793 * And evaluate it.
@@ -5803,7 +5815,7 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
58035815 * data. (makeConst would handle detoasting anyway, but it's worth a few
58045816 * extra lines here so that we can do the copy and detoast in one step.)
58055817 */
5806- if (!const_is_null )
5818+ if (!escontext . error_occurred && ! const_is_null )
58075819 {
58085820 if (resultTypLen == -1 )
58095821 const_val = PointerGetDatum (PG_DETOAST_DATUM_COPY (const_val ));
@@ -5814,6 +5826,9 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
58145826 /* Release all the junk we just created */
58155827 FreeExecutorState (estate );
58165828
5829+ if (escontext .error_occurred )
5830+ return NULL ;
5831+
58175832 /*
58185833 * Make the constant result node.
58195834 */
0 commit comments