On 22.09.23 02:38, Andy Fan wrote:
create table tb(a jsonb);

insert into tb select '{"a": "foo", "b": 100000000}';


select cast(a->'a' as numeric) from tb;

ERRCODE_INVALID_PARAMETER_VALUE  cannot cast jsonb string to type numeric

the call stack is:
0  in errstart of elog.c:351
1  in errstart_cold of elog.c:333
2  in cannotCastJsonbValue of jsonb.c:2033
3  in jsonb_numeric of jsonb.c:2063
4  in ExecInterpExpr of execExprInterp.c:758

select cast(a->'b' as int2) from tb;
NUMERIC_VALUE_OUT_OF_RANGE smallint out of range

the call stack is:
1  in errstart_cold of elog.c:333
2  in numeric_int2 of numeric.c:4503
3  in DirectFunctionCall1Coll of fmgr.c:785
4  in jsonb_int2 of jsonb.c:2086

There are 2 different errcode involved here and there are two different
functions that play part in it (jsonb_numeric and numeric_int2).  and
the error code jsonb_numeric used is improper as well.

This looks like an undesirable inconsistency.

You asked about the SQL standard. The error code NUMERIC_VALUE_OUT_OF_RANGE appears as part of a failure of the <cast specification>. The error code ERRCODE_INVALID_PARAMETER_VALUE appears only as part of processing host parameters in <externally-invoked procedure>. Of course, in PostgreSQL, function calls and casts are related under the hood, so you could maybe make arguments for both. But I think we already use ERRCODE_INVALID_PARAMETER_VALUE more broadly than the standard, so I would tend to prefer going in the direction of NUMERIC_VALUE_OUT_OF_RANGE when in doubt.

We could also consider these operators a special case of JSON_VALUE, in which case the following would apply:

"""
If IDT cannot be cast to target type DT according to the Syntax Rules of Subclause 6.13, “<cast specification>”, then let TEMPST be data exception — SQL/JSON item cannot be cast to target type (2203G).
"""

We do have a definition of this in errcodes.txt but don't use it anywhere. Maybe the patches for SQL/JSON currently being reviewed will use it.



Reply via email to