Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a5579a9

Browse files
committed
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
1 parent 13a255c commit a5579a9

File tree

3 files changed

+149
-7
lines changed

3 files changed

+149
-7
lines changed

src/backend/utils/adt/jsonb.c

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,7 +2040,16 @@ jsonb_bool(PG_FUNCTION_ARGS)
20402040
Jsonb *in = PG_GETARG_JSONB_P(0);
20412041
JsonbValue v;
20422042

2043-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
2043+
if (!JsonbExtractScalar(&in->root, &v))
2044+
cannotCastJsonbValue(v.type, "boolean");
2045+
2046+
if (v.type == jbvNull)
2047+
{
2048+
PG_FREE_IF_COPY(in, 0);
2049+
PG_RETURN_NULL();
2050+
}
2051+
2052+
if (v.type != jbvBool)
20442053
cannotCastJsonbValue(v.type, "boolean");
20452054

20462055
PG_FREE_IF_COPY(in, 0);
@@ -2055,7 +2064,16 @@ jsonb_numeric(PG_FUNCTION_ARGS)
20552064
JsonbValue v;
20562065
Numeric retValue;
20572066

2058-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2067+
if (!JsonbExtractScalar(&in->root, &v))
2068+
cannotCastJsonbValue(v.type, "numeric");
2069+
2070+
if (v.type == jbvNull)
2071+
{
2072+
PG_FREE_IF_COPY(in, 0);
2073+
PG_RETURN_NULL();
2074+
}
2075+
2076+
if (v.type != jbvNumeric)
20592077
cannotCastJsonbValue(v.type, "numeric");
20602078

20612079
/*
@@ -2076,7 +2094,16 @@ jsonb_int2(PG_FUNCTION_ARGS)
20762094
JsonbValue v;
20772095
Datum retValue;
20782096

2079-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2097+
if (!JsonbExtractScalar(&in->root, &v))
2098+
cannotCastJsonbValue(v.type, "smallint");
2099+
2100+
if (v.type == jbvNull)
2101+
{
2102+
PG_FREE_IF_COPY(in, 0);
2103+
PG_RETURN_NULL();
2104+
}
2105+
2106+
if (v.type != jbvNumeric)
20802107
cannotCastJsonbValue(v.type, "smallint");
20812108

20822109
retValue = DirectFunctionCall1(numeric_int2,
@@ -2094,7 +2121,16 @@ jsonb_int4(PG_FUNCTION_ARGS)
20942121
JsonbValue v;
20952122
Datum retValue;
20962123

2097-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2124+
if (!JsonbExtractScalar(&in->root, &v))
2125+
cannotCastJsonbValue(v.type, "integer");
2126+
2127+
if (v.type == jbvNull)
2128+
{
2129+
PG_FREE_IF_COPY(in, 0);
2130+
PG_RETURN_NULL();
2131+
}
2132+
2133+
if (v.type != jbvNumeric)
20982134
cannotCastJsonbValue(v.type, "integer");
20992135

21002136
retValue = DirectFunctionCall1(numeric_int4,
@@ -2112,7 +2148,16 @@ jsonb_int8(PG_FUNCTION_ARGS)
21122148
JsonbValue v;
21132149
Datum retValue;
21142150

2115-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2151+
if (!JsonbExtractScalar(&in->root, &v))
2152+
cannotCastJsonbValue(v.type, "bigint");
2153+
2154+
if (v.type == jbvNull)
2155+
{
2156+
PG_FREE_IF_COPY(in, 0);
2157+
PG_RETURN_NULL();
2158+
}
2159+
2160+
if (v.type != jbvNumeric)
21162161
cannotCastJsonbValue(v.type, "bigint");
21172162

21182163
retValue = DirectFunctionCall1(numeric_int8,
@@ -2130,7 +2175,16 @@ jsonb_float4(PG_FUNCTION_ARGS)
21302175
JsonbValue v;
21312176
Datum retValue;
21322177

2133-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2178+
if (!JsonbExtractScalar(&in->root, &v))
2179+
cannotCastJsonbValue(v.type, "real");
2180+
2181+
if (v.type == jbvNull)
2182+
{
2183+
PG_FREE_IF_COPY(in, 0);
2184+
PG_RETURN_NULL();
2185+
}
2186+
2187+
if (v.type != jbvNumeric)
21342188
cannotCastJsonbValue(v.type, "real");
21352189

21362190
retValue = DirectFunctionCall1(numeric_float4,
@@ -2148,7 +2202,16 @@ jsonb_float8(PG_FUNCTION_ARGS)
21482202
JsonbValue v;
21492203
Datum retValue;
21502204

2151-
if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2205+
if (!JsonbExtractScalar(&in->root, &v))
2206+
cannotCastJsonbValue(v.type, "double precision");
2207+
2208+
if (v.type == jbvNull)
2209+
{
2210+
PG_FREE_IF_COPY(in, 0);
2211+
PG_RETURN_NULL();
2212+
}
2213+
2214+
if (v.type != jbvNumeric)
21522215
cannotCastJsonbValue(v.type, "double precision");
21532216

21542217
retValue = DirectFunctionCall1(numeric_float8,

src/test/regress/expected/jsonb.out

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5617,6 +5617,12 @@ select 'true'::jsonb::bool;
56175617
t
56185618
(1 row)
56195619

5620+
select 'null'::jsonb::bool;
5621+
bool
5622+
------
5623+
5624+
(1 row)
5625+
56205626
select '[]'::jsonb::bool;
56215627
ERROR: cannot cast jsonb array to type boolean
56225628
select '1.0'::jsonb::float;
@@ -5625,22 +5631,82 @@ select '1.0'::jsonb::float;
56255631
1
56265632
(1 row)
56275633

5634+
select 'null'::jsonb::float;
5635+
float8
5636+
--------
5637+
5638+
(1 row)
5639+
56285640
select '[1.0]'::jsonb::float;
56295641
ERROR: cannot cast jsonb array to type double precision
5642+
select '1.0'::jsonb::float4;
5643+
float4
5644+
--------
5645+
1
5646+
(1 row)
5647+
5648+
select 'null'::jsonb::float4;
5649+
float4
5650+
--------
5651+
5652+
(1 row)
5653+
5654+
select '[1.0]'::jsonb::float4;
5655+
ERROR: cannot cast jsonb array to type real
5656+
select '12345'::jsonb::int2;
5657+
int2
5658+
-------
5659+
12345
5660+
(1 row)
5661+
5662+
select 'null'::jsonb::int2;
5663+
int2
5664+
------
5665+
5666+
(1 row)
5667+
5668+
select '"hello"'::jsonb::int2;
5669+
ERROR: cannot cast jsonb string to type smallint
56305670
select '12345'::jsonb::int4;
56315671
int4
56325672
-------
56335673
12345
56345674
(1 row)
56355675

5676+
select 'null'::jsonb::int4;
5677+
int4
5678+
------
5679+
5680+
(1 row)
5681+
56365682
select '"hello"'::jsonb::int4;
56375683
ERROR: cannot cast jsonb string to type integer
5684+
select '12345'::jsonb::int8;
5685+
int8
5686+
-------
5687+
12345
5688+
(1 row)
5689+
5690+
select 'null'::jsonb::int8;
5691+
int8
5692+
------
5693+
5694+
(1 row)
5695+
5696+
select '"hello"'::jsonb::int8;
5697+
ERROR: cannot cast jsonb string to type bigint
56385698
select '12345'::jsonb::numeric;
56395699
numeric
56405700
---------
56415701
12345
56425702
(1 row)
56435703

5704+
select 'null'::jsonb::numeric;
5705+
numeric
5706+
---------
5707+
5708+
(1 row)
5709+
56445710
select '{}'::jsonb::numeric;
56455711
ERROR: cannot cast jsonb object to type numeric
56465712
select '12345.05'::jsonb::numeric;

src/test/regress/sql/jsonb.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,12 +1540,25 @@ select ts_headline('[]'::jsonb, tsquery('aaa & bbb'));
15401540

15411541
-- casts
15421542
select 'true'::jsonb::bool;
1543+
select 'null'::jsonb::bool;
15431544
select '[]'::jsonb::bool;
15441545
select '1.0'::jsonb::float;
1546+
select 'null'::jsonb::float;
15451547
select '[1.0]'::jsonb::float;
1548+
select '1.0'::jsonb::float4;
1549+
select 'null'::jsonb::float4;
1550+
select '[1.0]'::jsonb::float4;
1551+
select '12345'::jsonb::int2;
1552+
select 'null'::jsonb::int2;
1553+
select '"hello"'::jsonb::int2;
15461554
select '12345'::jsonb::int4;
1555+
select 'null'::jsonb::int4;
15471556
select '"hello"'::jsonb::int4;
1557+
select '12345'::jsonb::int8;
1558+
select 'null'::jsonb::int8;
1559+
select '"hello"'::jsonb::int8;
15481560
select '12345'::jsonb::numeric;
1561+
select 'null'::jsonb::numeric;
15491562
select '{}'::jsonb::numeric;
15501563
select '12345.05'::jsonb::numeric;
15511564
select '12345.05'::jsonb::float4;

0 commit comments

Comments
 (0)