@@ -99,6 +99,9 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
9999static void ExecInitJsonExpr (JsonExpr * jsexpr , ExprState * state ,
100100 Datum * resv , bool * resnull ,
101101 ExprEvalStep * scratch );
102+ static void ExecInitSafeTypeCastExpr (SafeTypeCastExpr * stcexpr , ExprState * state ,
103+ Datum * resv , bool * resnull ,
104+ ExprEvalStep * scratch );
102105static void ExecInitJsonCoercion (ExprState * state , JsonReturning * returning ,
103106 ErrorSaveContext * escontext , bool omit_quotes ,
104107 bool exists_coerce ,
@@ -170,6 +173,47 @@ ExecInitExpr(Expr *node, PlanState *parent)
170173 return state ;
171174}
172175
176+ /*
177+ * ExecInitExprSafe: soft error variant of ExecInitExpr.
178+ *
179+ * use it only for expression nodes support soft errors, not all expression
180+ * nodes support it.
181+ */
182+ ExprState *
183+ ExecInitExprSafe (Expr * node , PlanState * parent )
184+ {
185+ ExprState * state ;
186+ ExprEvalStep scratch = {0 };
187+
188+ /* Special case: NULL expression produces a NULL ExprState pointer */
189+ if (node == NULL )
190+ return NULL ;
191+
192+ /* Initialize ExprState with empty step list */
193+ state = makeNode (ExprState );
194+ state -> expr = node ;
195+ state -> parent = parent ;
196+ state -> ext_params = NULL ;
197+ state -> escontext = makeNode (ErrorSaveContext );
198+ state -> escontext -> type = T_ErrorSaveContext ;
199+ state -> escontext -> error_occurred = false;
200+ state -> escontext -> details_wanted = false;
201+
202+ /* Insert setup steps as needed */
203+ ExecCreateExprSetupSteps (state , (Node * ) node );
204+
205+ /* Compile the expression proper */
206+ ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
207+
208+ /* Finally, append a DONE step */
209+ scratch .opcode = EEOP_DONE_RETURN ;
210+ ExprEvalPushStep (state , & scratch );
211+
212+ ExecReadyExpr (state );
213+
214+ return state ;
215+ }
216+
173217/*
174218 * ExecInitExprWithParams: prepare a standalone expression tree for execution
175219 *
@@ -1701,6 +1745,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
17011745
17021746 elemstate -> innermost_caseval = (Datum * ) palloc (sizeof (Datum ));
17031747 elemstate -> innermost_casenull = (bool * ) palloc (sizeof (bool ));
1748+ elemstate -> escontext = state -> escontext ;
17041749
17051750 ExecInitExprRec (acoerce -> elemexpr , elemstate ,
17061751 & elemstate -> resvalue , & elemstate -> resnull );
@@ -2177,6 +2222,14 @@ ExecInitExprRec(Expr *node, ExprState *state,
21772222 break ;
21782223 }
21792224
2225+ case T_SafeTypeCastExpr :
2226+ {
2227+ SafeTypeCastExpr * stcexpr = castNode (SafeTypeCastExpr , node );
2228+
2229+ ExecInitSafeTypeCastExpr (stcexpr , state , resv , resnull , & scratch );
2230+ break ;
2231+ }
2232+
21802233 case T_CoalesceExpr :
21812234 {
21822235 CoalesceExpr * coalesce = (CoalesceExpr * ) node ;
@@ -2743,7 +2796,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
27432796
27442797 /* Initialize function call parameter structure too */
27452798 InitFunctionCallInfoData (* fcinfo , flinfo ,
2746- nargs , inputcollid , NULL , NULL );
2799+ nargs , inputcollid , ( Node * ) state -> escontext , NULL );
27472800
27482801 /* Keep extra copies of this info to save an indirection at runtime */
27492802 scratch -> d .func .fn_addr = flinfo -> fn_addr ;
@@ -4741,6 +4794,68 @@ ExecBuildParamSetEqual(TupleDesc desc,
47414794 return state ;
47424795}
47434796
4797+ /*
4798+ * Push steps to evaluate a SafeTypeCastExpr and its various subsidiary
4799+ * expressions.
4800+ */
4801+ static void
4802+ ExecInitSafeTypeCastExpr (SafeTypeCastExpr * stcexpr , ExprState * state ,
4803+ Datum * resv , bool * resnull ,
4804+ ExprEvalStep * scratch )
4805+ {
4806+ /*
4807+ * If we can not coerce to the target type, fallback to the DEFAULT
4808+ * expression specified in the ON CONVERSION ERROR clause, and we are done.
4809+ */
4810+ if (stcexpr -> cast_expr == NULL )
4811+ {
4812+ ExecInitExprRec ((Expr * ) stcexpr -> default_expr ,
4813+ state , resv , resnull );
4814+ return ;
4815+ }
4816+ else
4817+ {
4818+ ExprEvalStep * as ;
4819+ SafeTypeCastState * stcstate ;
4820+ ErrorSaveContext * saved_escontext ;
4821+ int jumps_to_end ;
4822+
4823+ stcstate = palloc0 (sizeof (SafeTypeCastState ));
4824+ stcstate -> stcexpr = stcexpr ;
4825+ stcstate -> escontext .type = T_ErrorSaveContext ;
4826+ state -> escontext = & stcstate -> escontext ;
4827+
4828+ /* evaluate argument expression into step's result area */
4829+ ExecInitExprRec ((Expr * ) stcexpr -> cast_expr ,
4830+ state , resv , resnull );
4831+
4832+ scratch -> opcode = EEOP_SAFETYPE_CAST ;
4833+ scratch -> d .stcexpr .stcstate = stcstate ;
4834+ ExprEvalPushStep (state , scratch );
4835+ stcstate -> jump_error = state -> steps_len ;
4836+
4837+ /* JUMP to end if false, that is, skip the ON ERROR expression. */
4838+ jumps_to_end = state -> steps_len ;
4839+ scratch -> opcode = EEOP_JUMP_IF_NOT_TRUE ;
4840+ scratch -> resvalue = & stcstate -> error .value ;
4841+ scratch -> resnull = & stcstate -> error .isnull ;
4842+ scratch -> d .jump .jumpdone = -1 ; /* set below */
4843+ ExprEvalPushStep (state , scratch );
4844+
4845+ /* Steps to evaluate the ON ERROR expression */
4846+ saved_escontext = state -> escontext ;
4847+ state -> escontext = NULL ;
4848+ ExecInitExprRec ((Expr * ) stcstate -> stcexpr -> default_expr ,
4849+ state , resv , resnull );
4850+ state -> escontext = saved_escontext ;
4851+
4852+ as = & state -> steps [jumps_to_end ];
4853+ as -> d .jump .jumpdone = state -> steps_len ;
4854+
4855+ stcstate -> jump_end = state -> steps_len ;
4856+ }
4857+ }
4858+
47444859/*
47454860 * Push steps to evaluate a JsonExpr and its various subsidiary expressions.
47464861 */
0 commit comments