@@ -1857,15 +1857,19 @@ jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
1857
1857
/*
1858
1858
* Extract scalar value from raw-scalar pseudo-array jsonb.
1859
1859
*/
1860
- static JsonbValue *
1860
+ static bool
1861
1861
JsonbExtractScalar (JsonbContainer * jbc , JsonbValue * res )
1862
1862
{
1863
1863
JsonbIterator * it ;
1864
1864
JsonbIteratorToken tok PG_USED_FOR_ASSERTS_ONLY ;
1865
1865
JsonbValue tmp ;
1866
1866
1867
1867
if (!JsonContainerIsArray (jbc ) || !JsonContainerIsScalar (jbc ))
1868
- return NULL ;
1868
+ {
1869
+ /* inform caller about actual type of container */
1870
+ res -> type = (JsonContainerIsArray (jbc )) ? jbvArray : jbvObject ;
1871
+ return false;
1872
+ }
1869
1873
1870
1874
/*
1871
1875
* A root scalar is stored as an array of one element, so we get the array
@@ -1887,7 +1891,40 @@ JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
1887
1891
tok = JsonbIteratorNext (& it , & tmp , true);
1888
1892
Assert (tok == WJB_DONE );
1889
1893
1890
- return res ;
1894
+ return true;
1895
+ }
1896
+
1897
+ /*
1898
+ * Emit correct, translatable cast error message
1899
+ */
1900
+ static void
1901
+ cannotCastJsonbValue (enum jbvType type , const char * sqltype )
1902
+ {
1903
+ static const struct
1904
+ {
1905
+ enum jbvType type ;
1906
+ const char * msg ;
1907
+ }
1908
+ messages [] =
1909
+ {
1910
+ { jbvNull , gettext_noop ("cannot cast jsonb null to type %s" ) },
1911
+ { jbvString , gettext_noop ("cannot cast jsonb string to type %s" ) },
1912
+ { jbvNumeric , gettext_noop ("cannot cast jsonb numeric to type %s" ) },
1913
+ { jbvBool , gettext_noop ("cannot cast jsonb boolean to type %s" ) },
1914
+ { jbvArray , gettext_noop ("cannot cast jsonb array to type %s" ) },
1915
+ { jbvObject , gettext_noop ("cannot cast jsonb object to type %s" ) },
1916
+ { jbvBinary , gettext_noop ("cannot cast jsonb array or object to type %s" ) }
1917
+ };
1918
+ int i ;
1919
+
1920
+ for (i = 0 ; i < lengthof (messages ); i ++ )
1921
+ if (messages [i ].type == type )
1922
+ ereport (ERROR ,
1923
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1924
+ errmsg (messages [i ].msg , sqltype )));
1925
+
1926
+ /* should be unreachable */
1927
+ elog (ERROR , "unknown jsonb type: %d" , (int )type );
1891
1928
}
1892
1929
1893
1930
Datum
@@ -1897,9 +1934,7 @@ jsonb_bool(PG_FUNCTION_ARGS)
1897
1934
JsonbValue v ;
1898
1935
1899
1936
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvBool )
1900
- ereport (ERROR ,
1901
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1902
- errmsg ("jsonb value must be boolean" )));
1937
+ cannotCastJsonbValue (v .type , "boolean" );
1903
1938
1904
1939
PG_FREE_IF_COPY (in , 0 );
1905
1940
@@ -1914,9 +1949,7 @@ jsonb_numeric(PG_FUNCTION_ARGS)
1914
1949
Numeric retValue ;
1915
1950
1916
1951
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvNumeric )
1917
- ereport (ERROR ,
1918
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1919
- errmsg ("jsonb value must be numeric" )));
1952
+ cannotCastJsonbValue (v .type , "numeric" );
1920
1953
1921
1954
/*
1922
1955
* v.val.numeric points into jsonb body, so we need to make a copy to
@@ -1937,9 +1970,7 @@ jsonb_int2(PG_FUNCTION_ARGS)
1937
1970
Datum retValue ;
1938
1971
1939
1972
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvNumeric )
1940
- ereport (ERROR ,
1941
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1942
- errmsg ("jsonb value must be numeric" )));
1973
+ cannotCastJsonbValue (v .type , "smallint" );
1943
1974
1944
1975
retValue = DirectFunctionCall1 (numeric_int2 ,
1945
1976
NumericGetDatum (v .val .numeric ));
@@ -1957,9 +1988,7 @@ jsonb_int4(PG_FUNCTION_ARGS)
1957
1988
Datum retValue ;
1958
1989
1959
1990
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvNumeric )
1960
- ereport (ERROR ,
1961
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1962
- errmsg ("jsonb value must be numeric" )));
1991
+ cannotCastJsonbValue (v .type , "integer" );
1963
1992
1964
1993
retValue = DirectFunctionCall1 (numeric_int4 ,
1965
1994
NumericGetDatum (v .val .numeric ));
@@ -1977,9 +2006,7 @@ jsonb_int8(PG_FUNCTION_ARGS)
1977
2006
Datum retValue ;
1978
2007
1979
2008
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvNumeric )
1980
- ereport (ERROR ,
1981
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1982
- errmsg ("jsonb value must be numeric" )));
2009
+ cannotCastJsonbValue (v .type , "bigint" );
1983
2010
1984
2011
retValue = DirectFunctionCall1 (numeric_int8 ,
1985
2012
NumericGetDatum (v .val .numeric ));
@@ -1997,9 +2024,7 @@ jsonb_float4(PG_FUNCTION_ARGS)
1997
2024
Datum retValue ;
1998
2025
1999
2026
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvNumeric )
2000
- ereport (ERROR ,
2001
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
2002
- errmsg ("jsonb value must be numeric" )));
2027
+ cannotCastJsonbValue (v .type , "real" );
2003
2028
2004
2029
retValue = DirectFunctionCall1 (numeric_float4 ,
2005
2030
NumericGetDatum (v .val .numeric ));
@@ -2017,9 +2042,7 @@ jsonb_float8(PG_FUNCTION_ARGS)
2017
2042
Datum retValue ;
2018
2043
2019
2044
if (!JsonbExtractScalar (& in -> root , & v ) || v .type != jbvNumeric )
2020
- ereport (ERROR ,
2021
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
2022
- errmsg ("jsonb value must be numeric" )));
2045
+ cannotCastJsonbValue (v .type , "double precision" );
2023
2046
2024
2047
retValue = DirectFunctionCall1 (numeric_float8 ,
2025
2048
NumericGetDatum (v .val .numeric ));
0 commit comments