From 42fd50504556d2528f46a19d7c90e6b230986834 Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 24 Mar 2025 16:07:46 +0800 Subject: [PATCH v5 1/3] soft error variant of ExecPrepareExpr, ExecInitExpr ExecInitExprSafe: soft error of ExecInitExpr. ExecPrepareExprSafe: soft error of ExecPrepareExpr. ExecPrepareExprSafe initialize for expression execution with soft error support. not all expression node support it. Like node CoerceToDomain support it. XXX more comments. discussion: https://postgr.es/m/CACJufxE_+iZBR1i49k_AHigppPwLTJi6km8NOsC7FWvKdEmmXg@mail.gmail.com --- src/backend/executor/execExpr.c | 63 +++++++++++++++++++++++++++++++++ src/include/executor/executor.h | 2 ++ 2 files changed, 65 insertions(+) diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index f1569879b52..9182ba446a0 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -170,6 +170,47 @@ ExecInitExpr(Expr *node, PlanState *parent) return state; } +/* + * ExecInitExprSafe: soft error variant of ExecInitExpr. + * + * use it only for expression nodes support soft errors, not all expression + * nodes support it. +*/ +ExprState * +ExecInitExprSafe(Expr *node, PlanState *parent) +{ + ExprState *state; + ExprEvalStep scratch = {0}; + + /* Special case: NULL expression produces a NULL ExprState pointer */ + if (node == NULL) + return NULL; + + /* Initialize ExprState with empty step list */ + state = makeNode(ExprState); + state->expr = node; + state->parent = parent; + state->ext_params = NULL; + state->escontext = makeNode(ErrorSaveContext); + state->escontext->type = T_ErrorSaveContext; + state->escontext->error_occurred = false; + state->escontext->details_wanted = true; + + /* Insert setup steps as needed */ + ExecCreateExprSetupSteps(state, (Node *) node); + + /* Compile the expression proper */ + ExecInitExprRec(node, state, &state->resvalue, &state->resnull); + + /* Finally, append a DONE step */ + scratch.opcode = EEOP_DONE_RETURN; + ExprEvalPushStep(state, &scratch); + + ExecReadyExpr(state); + + return state; +} + /* * ExecInitExprWithParams: prepare a standalone expression tree for execution * @@ -778,6 +819,28 @@ ExecPrepareExpr(Expr *node, EState *estate) return result; } +/* + * ExecPrepareExprSafe: soft error variant of ExecPrepareExpr. + * + * use it when expression node *support* soft error expression execution. + */ +ExprState * +ExecPrepareExprSafe(Expr *node, EState *estate) +{ + ExprState *result; + MemoryContext oldcontext; + + oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + + node = expression_planner(node); + + result = ExecInitExprSafe(node, NULL); + + MemoryContextSwitchTo(oldcontext); + + return result; +} + /* * ExecPrepareQual --- initialize for qual execution outside a normal * Plan tree context. diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index ae99407db89..a26160042ee 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -346,6 +346,7 @@ ExecProcNode(PlanState *node) * prototypes from functions in execExpr.c */ extern ExprState *ExecInitExpr(Expr *node, PlanState *parent); +extern ExprState *ExecInitExprSafe(Expr *node, PlanState *parent); extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params); extern ExprState *ExecInitQual(List *qual, PlanState *parent); extern ExprState *ExecInitCheck(List *qual, PlanState *parent); @@ -394,6 +395,7 @@ extern ProjectionInfo *ExecBuildUpdateProjection(List *targetList, TupleTableSlot *slot, PlanState *parent); extern ExprState *ExecPrepareExpr(Expr *node, EState *estate); +extern ExprState *ExecPrepareExprSafe(Expr *node, EState *estate); extern ExprState *ExecPrepareQual(List *qual, EState *estate); extern ExprState *ExecPrepareCheck(List *qual, EState *estate); extern List *ExecPrepareExprList(List *nodes, EState *estate); -- 2.34.1