SQL/JSON DEFAULT ON ERROR/ON EMPTY evaluation fail should rethrow error unconditionally

From: jian he <jian(dot)universality(at)gmail(dot)com>
To: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Cc: Amit Langote <amitlangote09(at)gmail(dot)com>
Subject: SQL/JSON DEFAULT ON ERROR/ON EMPTY evaluation fail should rethrow error unconditionally
Date: 2026-09-16 02:21:20
Message-ID: CACJufxHDK39zF+1zZF6prH_wtn1SDt74_mrqYk1Oo82cCu44ng@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi.

Please see function ExecInitJsonExpr below code
``````
/*
* 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, false,
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);
}
``````
The above code relates to SQL/JSON ON ERROR, apply the same logic to ON EMPTY.

1.
The whole expression (jsexpr->on_error->expr) could be compiled under
the ErrorSaveContext, so any part of it
may report an error softly; without a COERCION_FINISH step afterwards
unconditionally, that
error is never handled.
That is not OK if we later want to raise the error, which is the case here.

2.
By the time the coercion step from ExecInitJsonCoercion runs, a soft error
may already have occurred during expression evaluation (DEFAULT ON
ERROR, DEFAULT ON EMPTY).
ExecEvalJsonCoercion should check for that first and, if so,
set resnull and resvalue and return earlier.

I found this issue while working on
https://commitfest.postgresql.org/patch/5941.

I don't think we need to add any extra comments.
/*
* Steps to evaluate the ON ERROR expression; handle errors softly to
* rethrow them in COERCION_FINISH step that will be added later.
*/
This comment is OK even if we unconditionally add a COERCION_FINISH step.

We could executing EEOP_JSONEXPR_COERCION_FINISH only when escontext
is non-NULL.
But, adding EEOP_JSONEXPR_COERCION_FINISH unconditionally feels more
intuitive and the cost seems very little.

--
jian
https://www.enterprisedb.com/

Attachment Content-Type Size
v1-0001-fix-SQL-JSON-DEFAULT-expression-error-rethrow.patch text/x-patch 9.2 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Amit Langote 2026-09-16 02:47:51 Re: SQL/JSON DEFAULT ON ERROR/ON EMPTY evaluation fail should rethrow error unconditionally
Previous Message Michael Paquier 2026-09-16 01:59:26 Re: Support for 8-byte TOAST values, round two