@@ -6,7 +6,7 @@ use datafusion::arrow::datatypes::{
66 DataType , Float32Type , Float64Type , Int16Type , Int32Type , Int64Type , Int8Type , UInt16Type , UInt32Type , UInt64Type ,
77 UInt8Type ,
88} ;
9- use datafusion:: common:: { exec_err, plan_err, Result as DataFusionResult , ScalarValue } ;
9+ use datafusion:: common:: { exec_datafusion_err , exec_err, plan_err, Result as DataFusionResult , ScalarValue } ;
1010use datafusion:: logical_expr:: { ColumnarValue , ScalarFunctionArgs , ScalarUDFImpl , Signature , Volatility } ;
1111
1212use crate :: common_macros:: make_udf_function;
@@ -16,7 +16,7 @@ make_udf_function!(
1616 JsonFromScalar ,
1717 json_from_scalar,
1818 value,
19- r# "Convert a scalar value (null, bool, integer, float, or string) to a JSON union type"#
19+ r"Convert a scalar value (null, bool, integer, float, or string) to a JSON union type"
2020) ;
2121
2222#[ derive( Debug , PartialEq , Eq , Hash ) ]
@@ -94,7 +94,7 @@ impl ScalarUDFImpl for JsonFromScalar {
9494 Ok ( ColumnarValue :: Scalar ( JsonUnionField :: scalar_value ( field) ) )
9595 }
9696 ColumnarValue :: Array ( array) => {
97- let union = array_to_json_union ( array) ?;
97+ let union = array_to_json_union ( & array) ?;
9898 let union_array: UnionArray = union. try_into ( ) ?;
9999 Ok ( ColumnarValue :: Array ( Arc :: new ( union_array) as ArrayRef ) )
100100 }
@@ -108,11 +108,24 @@ impl ScalarUDFImpl for JsonFromScalar {
108108
109109fn scalar_to_json_union_field ( scalar : ScalarValue ) -> DataFusionResult < Option < JsonUnionField > > {
110110 match scalar {
111- ScalarValue :: Null => Ok ( Some ( JsonUnionField :: JsonNull ) ) ,
112-
111+ // Null type / values
112+ ScalarValue :: Null
113+ | ScalarValue :: Boolean ( None )
114+ | ScalarValue :: Int8 ( None )
115+ | ScalarValue :: Int16 ( None )
116+ | ScalarValue :: Int32 ( None )
117+ | ScalarValue :: Int64 ( None )
118+ | ScalarValue :: UInt8 ( None )
119+ | ScalarValue :: UInt16 ( None )
120+ | ScalarValue :: UInt32 ( None )
121+ | ScalarValue :: UInt64 ( None )
122+ | ScalarValue :: Float32 ( None )
123+ | ScalarValue :: Float64 ( None )
124+ | ScalarValue :: Utf8 ( None )
125+ | ScalarValue :: LargeUtf8 ( None )
126+ | ScalarValue :: Utf8View ( None ) => Ok ( Some ( JsonUnionField :: JsonNull ) ) ,
127+ // Boolean type
113128 ScalarValue :: Boolean ( Some ( b) ) => Ok ( Some ( JsonUnionField :: Bool ( b) ) ) ,
114- ScalarValue :: Boolean ( None ) => Ok ( None ) ,
115-
116129 // Integer types - coerce to i64
117130 ScalarValue :: Int8 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Int ( i64:: from ( v) ) ) ) ,
118131 ScalarValue :: Int16 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Int ( i64:: from ( v) ) ) ) ,
@@ -121,35 +134,24 @@ fn scalar_to_json_union_field(scalar: ScalarValue) -> DataFusionResult<Option<Js
121134 ScalarValue :: UInt8 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Int ( i64:: from ( v) ) ) ) ,
122135 ScalarValue :: UInt16 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Int ( i64:: from ( v) ) ) ) ,
123136 ScalarValue :: UInt32 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Int ( i64:: from ( v) ) ) ) ,
124- ScalarValue :: UInt64 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Int ( v as i64 ) ) ) ,
125-
126- ScalarValue :: Int8 ( None )
127- | ScalarValue :: Int16 ( None )
128- | ScalarValue :: Int32 ( None )
129- | ScalarValue :: Int64 ( None )
130- | ScalarValue :: UInt8 ( None )
131- | ScalarValue :: UInt16 ( None )
132- | ScalarValue :: UInt32 ( None )
133- | ScalarValue :: UInt64 ( None ) => Ok ( Some ( JsonUnionField :: JsonNull ) ) ,
134-
137+ ScalarValue :: UInt64 ( Some ( v) ) => {
138+ Ok ( Some ( JsonUnionField :: Int ( i64:: try_from ( v) . map_err ( |_| {
139+ exec_datafusion_err ! ( "UInt64 value {} is out of range for i64" , v)
140+ } ) ?) ) )
141+ }
135142 // Float types - coerce to f64
136143 ScalarValue :: Float32 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Float ( f64:: from ( v) ) ) ) ,
137144 ScalarValue :: Float64 ( Some ( v) ) => Ok ( Some ( JsonUnionField :: Float ( v) ) ) ,
138- ScalarValue :: Float32 ( None ) | ScalarValue :: Float64 ( None ) => Ok ( Some ( JsonUnionField :: JsonNull ) ) ,
139-
140145 // String types
141146 ScalarValue :: Utf8 ( Some ( s) ) | ScalarValue :: LargeUtf8 ( Some ( s) ) | ScalarValue :: Utf8View ( Some ( s) ) => {
142147 Ok ( Some ( JsonUnionField :: Str ( s) ) )
143148 }
144- ScalarValue :: Utf8 ( None ) | ScalarValue :: LargeUtf8 ( None ) | ScalarValue :: Utf8View ( None ) => {
145- Ok ( Some ( JsonUnionField :: JsonNull ) )
146- }
147-
148149 _ => exec_err ! ( "Unsupported type for json_from_scalar: {:?}" , scalar. data_type( ) ) ,
149150 }
150151}
151152
152- fn array_to_json_union ( array : ArrayRef ) -> DataFusionResult < JsonUnion > {
153+ #[ expect( clippy:: too_many_lines) ]
154+ fn array_to_json_union ( array : & ArrayRef ) -> DataFusionResult < JsonUnion > {
153155 let mut union = JsonUnion :: new ( array. len ( ) ) ;
154156
155157 match array. data_type ( ) {
@@ -247,7 +249,9 @@ fn array_to_json_union(array: ArrayRef) -> DataFusionResult<JsonUnion> {
247249 if arr. is_null ( i) {
248250 union. push_none ( ) ;
249251 } else {
250- union. push ( JsonUnionField :: Int ( arr. value ( i) as i64 ) ) ;
252+ union. push ( JsonUnionField :: Int ( i64:: try_from ( arr. value ( i) ) . map_err ( |_| {
253+ exec_datafusion_err ! ( "UInt64 value {} is out of range for i64" , arr. value( i) )
254+ } ) ?) ) ;
251255 }
252256 }
253257 }
0 commit comments