From 1a37a56dfe6c807a8d61be3968120cf7fc4811de Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 26 Jan 2026 14:52:23 +0800
Subject: [PATCH v8 1/3] Enable soft error handling in ExecPrepareExpr and
 ExecInitExpr

discussion: https://postgr.es/m/CACJufxE_+iZBR1i49k_AHigppPwLTJi6km8NOsC7FWvKdEmmXg@mail.gmail.com
commitfest: https://commitfest.postgresql.org/patch/5641
---
 src/backend/executor/execExpr.c | 21 ++++++++++++++++++++-
 src/include/executor/executor.h |  2 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 088eca24021..765e90494a5 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -141,6 +141,18 @@ static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning,
  */
 ExprState *
 ExecInitExpr(Expr *node, PlanState *parent)
+{
+	return ExecInitExprExtended(node, parent, NULL);
+}
+
+/*
+ * 'escontext' is expected to be non-NULL only for expression nodes that support
+ * soft errors.
+ *
+ * Not all expression nodes support this; if in doubt, pass NULL.
+ */
+ExprState *
+ExecInitExprExtended(Expr *node, PlanState *parent, Node *escontext)
 {
 	ExprState  *state;
 	ExprEvalStep scratch = {0};
@@ -154,6 +166,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
 	state->expr = node;
 	state->parent = parent;
 	state->ext_params = NULL;
+	state->escontext = (ErrorSaveContext *) escontext;
 
 	/* Insert setup steps as needed */
 	ExecCreateExprSetupSteps(state, (Node *) node);
@@ -763,6 +776,12 @@ ExecBuildUpdateProjection(List *targetList,
  */
 ExprState *
 ExecPrepareExpr(Expr *node, EState *estate)
+{
+	return ExecPrepareExprExtended(node, estate, NULL);
+}
+
+ExprState *
+ExecPrepareExprExtended(Expr *node, EState *estate, Node *escontext)
 {
 	ExprState  *result;
 	MemoryContext oldcontext;
@@ -771,7 +790,7 @@ ExecPrepareExpr(Expr *node, EState *estate)
 
 	node = expression_planner(node);
 
-	result = ExecInitExpr(node, NULL);
+	result = ExecInitExprExtended(node, NULL, escontext);
 
 	MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 5929aabc353..a53d60107cb 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -324,6 +324,7 @@ ExecProcNode(PlanState *node)
  * prototypes from functions in execExpr.c
  */
 extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
+extern ExprState *ExecInitExprExtended(Expr *node, PlanState *parent, Node *escontext);
 extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params);
 extern ExprState *ExecInitQual(List *qual, PlanState *parent);
 extern ExprState *ExecInitCheck(List *qual, PlanState *parent);
@@ -372,6 +373,7 @@ extern ProjectionInfo *ExecBuildUpdateProjection(List *targetList,
 												 TupleTableSlot *slot,
 												 PlanState *parent);
 extern ExprState *ExecPrepareExpr(Expr *node, EState *estate);
+extern ExprState *ExecPrepareExprExtended(Expr *node, EState *estate, Node *escontext);
 extern ExprState *ExecPrepareQual(List *qual, EState *estate);
 extern ExprState *ExecPrepareCheck(List *qual, EState *estate);
 extern List *ExecPrepareExprList(List *nodes, EState *estate);
-- 
2.34.1

