diff options
-rw-r--r-- | src/backend/utils/adt/jsonb.c | 77 | ||||
-rw-r--r-- | src/test/regress/expected/jsonb.out | 66 | ||||
-rw-r--r-- | src/test/regress/sql/jsonb.sql | 13 |
3 files changed, 149 insertions, 7 deletions
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index f4889d9ed72..8394a20e0e5 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -2040,7 +2040,16 @@ jsonb_bool(PG_FUNCTION_ARGS) Jsonb *in = PG_GETARG_JSONB_P(0); 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"); PG_FREE_IF_COPY(in, 0); @@ -2055,7 +2064,16 @@ jsonb_numeric(PG_FUNCTION_ARGS) JsonbValue v; 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"); /* @@ -2076,7 +2094,16 @@ jsonb_int2(PG_FUNCTION_ARGS) JsonbValue v; 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"); retValue = DirectFunctionCall1(numeric_int2, @@ -2094,7 +2121,16 @@ jsonb_int4(PG_FUNCTION_ARGS) JsonbValue v; 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"); retValue = DirectFunctionCall1(numeric_int4, @@ -2112,7 +2148,16 @@ jsonb_int8(PG_FUNCTION_ARGS) JsonbValue v; 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"); retValue = DirectFunctionCall1(numeric_int8, @@ -2130,7 +2175,16 @@ jsonb_float4(PG_FUNCTION_ARGS) JsonbValue v; 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"); retValue = DirectFunctionCall1(numeric_float4, @@ -2148,7 +2202,16 @@ jsonb_float8(PG_FUNCTION_ARGS) JsonbValue v; 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"); retValue = DirectFunctionCall1(numeric_float8, diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 7d163a156e3..2baff931bf2 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -5617,6 +5617,12 @@ select 'true'::jsonb::bool; t (1 row) +select 'null'::jsonb::bool; + bool +------ + +(1 row) + select '[]'::jsonb::bool; ERROR: cannot cast jsonb array to type boolean select '1.0'::jsonb::float; @@ -5625,22 +5631,82 @@ select '1.0'::jsonb::float; 1 (1 row) +select 'null'::jsonb::float; + float8 +-------- + +(1 row) + select '[1.0]'::jsonb::float; 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; int4 ------- 12345 (1 row) +select 'null'::jsonb::int4; + int4 +------ + +(1 row) + select '"hello"'::jsonb::int4; 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; numeric --------- 12345 (1 row) +select 'null'::jsonb::numeric; + numeric +--------- + +(1 row) + select '{}'::jsonb::numeric; ERROR: cannot cast jsonb object to type numeric select '12345.05'::jsonb::numeric; diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 5f0190d5a2b..544bb610e2d 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -1540,12 +1540,25 @@ select ts_headline('[]'::jsonb, tsquery('aaa & bbb')); -- casts select 'true'::jsonb::bool; +select 'null'::jsonb::bool; select '[]'::jsonb::bool; select '1.0'::jsonb::float; +select 'null'::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 'null'::jsonb::int4; select '"hello"'::jsonb::int4; +select '12345'::jsonb::int8; +select 'null'::jsonb::int8; +select '"hello"'::jsonb::int8; select '12345'::jsonb::numeric; +select 'null'::jsonb::numeric; select '{}'::jsonb::numeric; select '12345.05'::jsonb::numeric; select '12345.05'::jsonb::float4; |