@@ -4400,6 +4400,8 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
4400
4400
if (jsexpr -> on_error &&
4401
4401
jsexpr -> on_error -> btype != JSON_BEHAVIOR_ERROR )
4402
4402
{
4403
+ ErrorSaveContext * saved_escontext ;
4404
+
4403
4405
jsestate -> jump_error = state -> steps_len ;
4404
4406
4405
4407
/* JUMP to end if false, that is, skip the ON ERROR expression. */
@@ -4410,15 +4412,36 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
4410
4412
scratch -> d .jump .jumpdone = -1 ; /* set below */
4411
4413
ExprEvalPushStep (state , scratch );
4412
4414
4413
- /* Steps to evaluate the ON ERROR expression */
4415
+ /*
4416
+ * Steps to evaluate the ON ERROR expression; handle errors softly to
4417
+ * rethrow them in COERCION_FINISH step that will be added later.
4418
+ */
4419
+ saved_escontext = state -> escontext ;
4420
+ state -> escontext = escontext ;
4414
4421
ExecInitExprRec ((Expr * ) jsexpr -> on_error -> expr ,
4415
4422
state , resv , resnull );
4423
+ state -> escontext = saved_escontext ;
4416
4424
4417
4425
/* Step to coerce the ON ERROR expression if needed */
4418
4426
if (jsexpr -> on_error -> coerce )
4419
4427
ExecInitJsonCoercion (state , jsexpr -> returning , escontext ,
4420
4428
jsexpr -> omit_quotes , resv , resnull );
4421
4429
4430
+ /*
4431
+ * Add a COERCION_FINISH step to check for errors that may occur when
4432
+ * coercing and rethrow them.
4433
+ */
4434
+ if (jsexpr -> on_error -> coerce ||
4435
+ IsA (jsexpr -> on_error -> expr , CoerceViaIO ) ||
4436
+ IsA (jsexpr -> on_error -> expr , CoerceToDomain ))
4437
+ {
4438
+ scratch -> opcode = EEOP_JSONEXPR_COERCION_FINISH ;
4439
+ scratch -> resvalue = resv ;
4440
+ scratch -> resnull = resnull ;
4441
+ scratch -> d .jsonexpr .jsestate = jsestate ;
4442
+ ExprEvalPushStep (state , scratch );
4443
+ }
4444
+
4422
4445
/* JUMP to end to skip the ON EMPTY steps added below. */
4423
4446
jumps_to_end = lappend_int (jumps_to_end , state -> steps_len );
4424
4447
scratch -> opcode = EEOP_JUMP ;
@@ -4433,6 +4456,8 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
4433
4456
if (jsexpr -> on_empty != NULL &&
4434
4457
jsexpr -> on_empty -> btype != JSON_BEHAVIOR_ERROR )
4435
4458
{
4459
+ ErrorSaveContext * saved_escontext ;
4460
+
4436
4461
jsestate -> jump_empty = state -> steps_len ;
4437
4462
4438
4463
/* JUMP to end if false, that is, skip the ON EMPTY expression. */
@@ -4443,14 +4468,36 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
4443
4468
scratch -> d .jump .jumpdone = -1 ; /* set below */
4444
4469
ExprEvalPushStep (state , scratch );
4445
4470
4446
- /* Steps to evaluate the ON EMPTY expression */
4471
+ /*
4472
+ * Steps to evaluate the ON EMPTY expression; handle errors softly to
4473
+ * rethrow them in COERCION_FINISH step that will be added later.
4474
+ */
4475
+ saved_escontext = state -> escontext ;
4476
+ state -> escontext = escontext ;
4447
4477
ExecInitExprRec ((Expr * ) jsexpr -> on_empty -> expr ,
4448
4478
state , resv , resnull );
4479
+ state -> escontext = saved_escontext ;
4449
4480
4450
4481
/* Step to coerce the ON EMPTY expression if needed */
4451
4482
if (jsexpr -> on_empty -> coerce )
4452
4483
ExecInitJsonCoercion (state , jsexpr -> returning , escontext ,
4453
4484
jsexpr -> omit_quotes , resv , resnull );
4485
+
4486
+ /*
4487
+ * Add a COERCION_FINISH step to check for errors that may occur when
4488
+ * coercing and rethrow them.
4489
+ */
4490
+ if (jsexpr -> on_empty -> coerce ||
4491
+ IsA (jsexpr -> on_empty -> expr , CoerceViaIO ) ||
4492
+ IsA (jsexpr -> on_empty -> expr , CoerceToDomain ))
4493
+ {
4494
+
4495
+ scratch -> opcode = EEOP_JSONEXPR_COERCION_FINISH ;
4496
+ scratch -> resvalue = resv ;
4497
+ scratch -> resnull = resnull ;
4498
+ scratch -> d .jsonexpr .jsestate = jsestate ;
4499
+ ExprEvalPushStep (state , scratch );
4500
+ }
4454
4501
}
4455
4502
4456
4503
foreach (lc , jumps_to_end )
0 commit comments