SQL/JSON: always rethrow soft errors from DEFAULT expressions
The DEFAULT expression of an ON ERROR or ON EMPTY clause is compiled
with the JsonExpr's ErrorSaveContext in effect, so that any error
raised while evaluating it is saved rather than thrown and can be
reported later as "could not coerce ON ERROR expression (DEFAULT) to
the RETURNING type". That reporting is done by an
EEOP_JSONEXPR_COERCION_FINISH step, but ExecInitJsonExpr only added
that step when the DEFAULT expression needed a runtime coercion, or
when its top-level node was a CoerceViaIO or a CoerceToDomain. Those
are not the only nodes that can save an error: the ErrorSaveContext
applies to the whole expression tree, so a cast nested inside, say,
an OpExpr saves its error just the same. In that case there was
nothing to rethrow it and the query silently returned NULL instead
of failing, for example:
SELECT JSON_VALUE('"a"', '$' RETURNING int
DEFAULT (('a' || (random() * 0)::int)::int + 0)
ON ERROR);
Fix by adding the COERCION_FINISH step after every DEFAULT expression
that is evaluated softly, that is, whenever the ON ERROR behavior is
not ERROR.
Reported-by: jian he <[email protected]>
Author: jian he <[email protected]>
Discussion:
https://postgr.es/m/cacjufxhdk39zf+1zzf6prh_wtn1sdt74_mrqyk1oo82ccu4...@mail.gmail.com
Backpatch-through: 17
Branch
------
REL_19_STABLE
Details
-------
https://git.postgresql.org/pg/commitdiff/6839997e332281576c02c926a711df1edc50e371
Modified Files
--------------
src/backend/executor/execExpr.c | 35 ++++++++++--------------
src/test/regress/expected/sqljson_jsontable.out | 13 +++++++++
src/test/regress/expected/sqljson_queryfuncs.out | 17 ++++++++++++
src/test/regress/sql/sqljson_jsontable.sql | 5 ++++
src/test/regress/sql/sqljson_queryfuncs.sql | 8 ++++++
5 files changed, 58 insertions(+), 20 deletions(-)