1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +03:00

Make jsonb casts to scalar types translate JSON null to SQL NULL.

Formerly, these cases threw an error "cannot cast jsonb null to type
<whatever>".  That seems less than helpful though.  It's also
inconsistent with the behavior of the ->> operator, which translates
JSON null to SQL NULL, as do some other jsonb functions.

Discussion: https://postgr.es/m/3851203.1722552717@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2025-01-24 13:20:44 -05:00
parent 13a255c195
commit a5579a90af
3 changed files with 149 additions and 7 deletions

View File

@ -2040,7 +2040,16 @@ jsonb_bool(PG_FUNCTION_ARGS)
Jsonb *in = PG_GETARG_JSONB_P(0); Jsonb *in = PG_GETARG_JSONB_P(0);
JsonbValue v; JsonbValue v;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "boolean");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvBool)
cannotCastJsonbValue(v.type, "boolean"); cannotCastJsonbValue(v.type, "boolean");
PG_FREE_IF_COPY(in, 0); PG_FREE_IF_COPY(in, 0);
@ -2055,7 +2064,16 @@ jsonb_numeric(PG_FUNCTION_ARGS)
JsonbValue v; JsonbValue v;
Numeric retValue; Numeric retValue;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "numeric");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvNumeric)
cannotCastJsonbValue(v.type, "numeric"); cannotCastJsonbValue(v.type, "numeric");
/* /*
@ -2076,7 +2094,16 @@ jsonb_int2(PG_FUNCTION_ARGS)
JsonbValue v; JsonbValue v;
Datum retValue; Datum retValue;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "smallint");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvNumeric)
cannotCastJsonbValue(v.type, "smallint"); cannotCastJsonbValue(v.type, "smallint");
retValue = DirectFunctionCall1(numeric_int2, retValue = DirectFunctionCall1(numeric_int2,
@ -2094,7 +2121,16 @@ jsonb_int4(PG_FUNCTION_ARGS)
JsonbValue v; JsonbValue v;
Datum retValue; Datum retValue;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "integer");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvNumeric)
cannotCastJsonbValue(v.type, "integer"); cannotCastJsonbValue(v.type, "integer");
retValue = DirectFunctionCall1(numeric_int4, retValue = DirectFunctionCall1(numeric_int4,
@ -2112,7 +2148,16 @@ jsonb_int8(PG_FUNCTION_ARGS)
JsonbValue v; JsonbValue v;
Datum retValue; Datum retValue;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "bigint");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvNumeric)
cannotCastJsonbValue(v.type, "bigint"); cannotCastJsonbValue(v.type, "bigint");
retValue = DirectFunctionCall1(numeric_int8, retValue = DirectFunctionCall1(numeric_int8,
@ -2130,7 +2175,16 @@ jsonb_float4(PG_FUNCTION_ARGS)
JsonbValue v; JsonbValue v;
Datum retValue; Datum retValue;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "real");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvNumeric)
cannotCastJsonbValue(v.type, "real"); cannotCastJsonbValue(v.type, "real");
retValue = DirectFunctionCall1(numeric_float4, retValue = DirectFunctionCall1(numeric_float4,
@ -2148,7 +2202,16 @@ jsonb_float8(PG_FUNCTION_ARGS)
JsonbValue v; JsonbValue v;
Datum retValue; Datum retValue;
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) if (!JsonbExtractScalar(&in->root, &v))
cannotCastJsonbValue(v.type, "double precision");
if (v.type == jbvNull)
{
PG_FREE_IF_COPY(in, 0);
PG_RETURN_NULL();
}
if (v.type != jbvNumeric)
cannotCastJsonbValue(v.type, "double precision"); cannotCastJsonbValue(v.type, "double precision");
retValue = DirectFunctionCall1(numeric_float8, retValue = DirectFunctionCall1(numeric_float8,

View File

@ -5617,6 +5617,12 @@ select 'true'::jsonb::bool;
t t
(1 row) (1 row)
select 'null'::jsonb::bool;
bool
------
(1 row)
select '[]'::jsonb::bool; select '[]'::jsonb::bool;
ERROR: cannot cast jsonb array to type boolean ERROR: cannot cast jsonb array to type boolean
select '1.0'::jsonb::float; select '1.0'::jsonb::float;
@ -5625,22 +5631,82 @@ select '1.0'::jsonb::float;
1 1
(1 row) (1 row)
select 'null'::jsonb::float;
float8
--------
(1 row)
select '[1.0]'::jsonb::float; select '[1.0]'::jsonb::float;
ERROR: cannot cast jsonb array to type double precision ERROR: cannot cast jsonb array to type double precision
select '1.0'::jsonb::float4;
float4
--------
1
(1 row)
select 'null'::jsonb::float4;
float4
--------
(1 row)
select '[1.0]'::jsonb::float4;
ERROR: cannot cast jsonb array to type real
select '12345'::jsonb::int2;
int2
-------
12345
(1 row)
select 'null'::jsonb::int2;
int2
------
(1 row)
select '"hello"'::jsonb::int2;
ERROR: cannot cast jsonb string to type smallint
select '12345'::jsonb::int4; select '12345'::jsonb::int4;
int4 int4
------- -------
12345 12345
(1 row) (1 row)
select 'null'::jsonb::int4;
int4
------
(1 row)
select '"hello"'::jsonb::int4; select '"hello"'::jsonb::int4;
ERROR: cannot cast jsonb string to type integer ERROR: cannot cast jsonb string to type integer
select '12345'::jsonb::int8;
int8
-------
12345
(1 row)
select 'null'::jsonb::int8;
int8
------
(1 row)
select '"hello"'::jsonb::int8;
ERROR: cannot cast jsonb string to type bigint
select '12345'::jsonb::numeric; select '12345'::jsonb::numeric;
numeric numeric
--------- ---------
12345 12345
(1 row) (1 row)
select 'null'::jsonb::numeric;
numeric
---------
(1 row)
select '{}'::jsonb::numeric; select '{}'::jsonb::numeric;
ERROR: cannot cast jsonb object to type numeric ERROR: cannot cast jsonb object to type numeric
select '12345.05'::jsonb::numeric; select '12345.05'::jsonb::numeric;

View File

@ -1540,12 +1540,25 @@ select ts_headline('[]'::jsonb, tsquery('aaa & bbb'));
-- casts -- casts
select 'true'::jsonb::bool; select 'true'::jsonb::bool;
select 'null'::jsonb::bool;
select '[]'::jsonb::bool; select '[]'::jsonb::bool;
select '1.0'::jsonb::float; select '1.0'::jsonb::float;
select 'null'::jsonb::float;
select '[1.0]'::jsonb::float; select '[1.0]'::jsonb::float;
select '1.0'::jsonb::float4;
select 'null'::jsonb::float4;
select '[1.0]'::jsonb::float4;
select '12345'::jsonb::int2;
select 'null'::jsonb::int2;
select '"hello"'::jsonb::int2;
select '12345'::jsonb::int4; select '12345'::jsonb::int4;
select 'null'::jsonb::int4;
select '"hello"'::jsonb::int4; select '"hello"'::jsonb::int4;
select '12345'::jsonb::int8;
select 'null'::jsonb::int8;
select '"hello"'::jsonb::int8;
select '12345'::jsonb::numeric; select '12345'::jsonb::numeric;
select 'null'::jsonb::numeric;
select '{}'::jsonb::numeric; select '{}'::jsonb::numeric;
select '12345.05'::jsonb::numeric; select '12345.05'::jsonb::numeric;
select '12345.05'::jsonb::float4; select '12345.05'::jsonb::float4;