diff options
Diffstat (limited to 'src/backend/executor/execExpr.c')
-rw-r--r-- | src/backend/executor/execExpr.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index ccd48637784..b10359e3d6b 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -4400,6 +4400,8 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, if (jsexpr->on_error && jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR) { + ErrorSaveContext *saved_escontext; + jsestate->jump_error = state->steps_len; /* JUMP to end if false, that is, skip the ON ERROR expression. */ @@ -4410,15 +4412,36 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, scratch->d.jump.jumpdone = -1; /* set below */ ExprEvalPushStep(state, scratch); - /* Steps to evaluate the ON ERROR expression */ + /* + * Steps to evaluate the ON ERROR expression; handle errors softly to + * rethrow them in COERCION_FINISH step that will be added later. + */ + saved_escontext = state->escontext; + state->escontext = escontext; ExecInitExprRec((Expr *) jsexpr->on_error->expr, state, resv, resnull); + state->escontext = saved_escontext; /* Step to coerce the ON ERROR expression if needed */ if (jsexpr->on_error->coerce) ExecInitJsonCoercion(state, jsexpr->returning, escontext, jsexpr->omit_quotes, resv, resnull); + /* + * Add a COERCION_FINISH step to check for errors that may occur when + * coercing and rethrow them. + */ + if (jsexpr->on_error->coerce || + IsA(jsexpr->on_error->expr, CoerceViaIO) || + IsA(jsexpr->on_error->expr, CoerceToDomain)) + { + scratch->opcode = EEOP_JSONEXPR_COERCION_FINISH; + scratch->resvalue = resv; + scratch->resnull = resnull; + scratch->d.jsonexpr.jsestate = jsestate; + ExprEvalPushStep(state, scratch); + } + /* JUMP to end to skip the ON EMPTY steps added below. */ jumps_to_end = lappend_int(jumps_to_end, state->steps_len); scratch->opcode = EEOP_JUMP; @@ -4433,6 +4456,8 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, if (jsexpr->on_empty != NULL && jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR) { + ErrorSaveContext *saved_escontext; + jsestate->jump_empty = state->steps_len; /* JUMP to end if false, that is, skip the ON EMPTY expression. */ @@ -4443,14 +4468,36 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, scratch->d.jump.jumpdone = -1; /* set below */ ExprEvalPushStep(state, scratch); - /* Steps to evaluate the ON EMPTY expression */ + /* + * Steps to evaluate the ON EMPTY expression; handle errors softly to + * rethrow them in COERCION_FINISH step that will be added later. + */ + saved_escontext = state->escontext; + state->escontext = escontext; ExecInitExprRec((Expr *) jsexpr->on_empty->expr, state, resv, resnull); + state->escontext = saved_escontext; /* Step to coerce the ON EMPTY expression if needed */ if (jsexpr->on_empty->coerce) ExecInitJsonCoercion(state, jsexpr->returning, escontext, jsexpr->omit_quotes, resv, resnull); + + /* + * Add a COERCION_FINISH step to check for errors that may occur when + * coercing and rethrow them. + */ + if (jsexpr->on_empty->coerce || + IsA(jsexpr->on_empty->expr, CoerceViaIO) || + IsA(jsexpr->on_empty->expr, CoerceToDomain)) + { + + scratch->opcode = EEOP_JSONEXPR_COERCION_FINISH; + scratch->resvalue = resv; + scratch->resnull = resnull; + scratch->d.jsonexpr.jsestate = jsestate; + ExprEvalPushStep(state, scratch); + } } foreach(lc, jumps_to_end) |