@@ -22,41 +22,72 @@ use arrow::datatypes::DataType;
2222use datafusion:: common:: { exec_err, internal_err, DataFusionError , ScalarValue } ;
2323use datafusion:: { functions:: math:: round:: round, physical_plan:: ColumnarValue } ;
2424use std:: { cmp:: min, sync:: Arc } ;
25+ use crate :: SparkError ;
2526
2627macro_rules! integer_round {
27- ( $X: expr, $DIV: expr, $HALF: expr) => { {
28+ ( $X: expr, $DIV: expr, $HALF: expr, $FAIL_ON_ERROR : expr ) => { {
2829 let rem = $X % $DIV;
2930 if rem <= -$HALF {
30- ( $X - rem) . sub_wrapping( $DIV)
31+ if ( $FAIL_ON_ERROR) {
32+ match ( $X - rem) . sub_checked( $DIV) {
33+ Ok ( v) => v,
34+ Err ( _) => {
35+ return Err ( SparkError :: ArithmeticOverflow { from_type: String :: from( "integer" ) , } . into( ) ) ;
36+ }
37+ }
38+ }
39+ else{
40+ ( $X - rem) . sub_wrapping( $DIV)
41+ }
3142 } else if rem >= $HALF {
32- ( $X - rem) . add_wrapping( $DIV)
43+ if ( $FAIL_ON_ERROR) {
44+ match ( $X - rem) . add_checked( $DIV) {
45+ Ok ( v) => v,
46+ Err ( _) => {
47+ return Err ( SparkError :: ArithmeticOverflow { from_type: String :: from( "integer" ) } . into( ) ) ;
48+ }
49+ }
50+ }
51+ else{
52+ ( $X - rem) . add_wrapping( $DIV)
53+ }
3354 } else {
34- $X - rem
55+ if ( $FAIL_ON_ERROR) {
56+ match ( $X - rem) . sub_checked( /* i64 */ ) {
57+ Ok ( v) => v,
58+ Err ( _) => {
59+ return Err ( SparkError :: ArithmeticOverflow { from_type: String :: from( "integer" ) } . into( ) ) ;
60+ }
61+ }
62+ }
63+ else{
64+ $X - rem
65+ }
3566 }
3667 } } ;
3768}
3869
3970macro_rules! round_integer_array {
40- ( $ARRAY: expr, $POINT: expr, $TYPE: ty, $NATIVE: ty) => { {
71+ ( $ARRAY: expr, $POINT: expr, $TYPE: ty, $NATIVE: ty, $FAIL_ON_ERROR : expr ) => { {
4172 let array = $ARRAY. as_any( ) . downcast_ref:: <$TYPE>( ) . unwrap( ) ;
4273 let ten: $NATIVE = 10 ;
43- let result: $TYPE = if let Some ( div) = ten. checked_pow( ( -( * $POINT) ) as u32 ) {
74+ let result = if let Some ( div) = ten. checked_pow( ( -( * $POINT) ) as u32 ) {
4475 let half = div / 2 ;
45- arrow:: compute:: kernels:: arity:: unary ( array, |x| integer_round!( x, div, half) )
76+ arrow:: compute:: kernels:: arity:: try_unary ( array, |x| integer_round!( x, div, half, $FAIL_ON_ERROR ) )
4677 } else {
47- arrow:: compute:: kernels:: arity:: unary ( array, |_| 0 )
48- } ;
78+ arrow:: compute:: kernels:: arity:: try_unary ( array, |_| 0 )
79+ } . map_err ( |e| DataFusionError :: ArrowError ( e ) ) ? ;
4980 Ok ( ColumnarValue :: Array ( Arc :: new( result) ) )
5081 } } ;
5182}
5283
5384macro_rules! round_integer_scalar {
54- ( $SCALAR: expr, $POINT: expr, $TYPE: expr, $NATIVE: ty) => { {
85+ ( $SCALAR: expr, $POINT: expr, $TYPE: expr, $NATIVE: ty, $FAIL_ON_ERROR : expr ) => { {
5586 let ten: $NATIVE = 10 ;
5687 if let Some ( div) = ten. checked_pow( ( -( * $POINT) ) as u32 ) {
5788 let half = div / 2 ;
5889 Ok ( ColumnarValue :: Scalar ( $TYPE(
59- $SCALAR. map( |x| integer_round!( x, div, half) ) ,
90+ $SCALAR. map( |x| integer_round!( x, div, half, $FAIL_ON_ERROR ) ) ,
6091 ) ) )
6192 } else {
6293 Ok ( ColumnarValue :: Scalar ( $TYPE( Some ( 0 ) ) ) )
@@ -68,6 +99,7 @@ macro_rules! round_integer_scalar {
6899pub fn spark_round (
69100 args : & [ ColumnarValue ] ,
70101 data_type : & DataType ,
102+ fail_on_error : bool
71103) -> Result < ColumnarValue , DataFusionError > {
72104 let value = & args[ 0 ] ;
73105 let point = & args[ 1 ] ;
@@ -76,10 +108,10 @@ pub fn spark_round(
76108 } ;
77109 match value {
78110 ColumnarValue :: Array ( array) => match array. data_type ( ) {
79- DataType :: Int64 if * point < 0 => round_integer_array ! ( array, point, Int64Array , i64 ) ,
80- DataType :: Int32 if * point < 0 => round_integer_array ! ( array, point, Int32Array , i32 ) ,
81- DataType :: Int16 if * point < 0 => round_integer_array ! ( array, point, Int16Array , i16 ) ,
82- DataType :: Int8 if * point < 0 => round_integer_array ! ( array, point, Int8Array , i8 ) ,
111+ DataType :: Int64 if * point < 0 => round_integer_array ! ( array, point, Int64Array , i64 , fail_on_error ) ,
112+ DataType :: Int32 if * point < 0 => round_integer_array ! ( array, point, Int32Array , i32 , fail_on_error ) ,
113+ DataType :: Int16 if * point < 0 => round_integer_array ! ( array, point, Int16Array , i16 , fail_on_error ) ,
114+ DataType :: Int8 if * point < 0 => round_integer_array ! ( array, point, Int8Array , i8 , fail_on_error ) ,
83115 DataType :: Decimal128 ( _, scale) if * scale >= 0 => {
84116 let f = decimal_round_f ( scale, point) ;
85117 let ( precision, scale) = get_precision_scale ( data_type) ;
@@ -93,16 +125,16 @@ pub fn spark_round(
93125 } ,
94126 ColumnarValue :: Scalar ( a) => match a {
95127 ScalarValue :: Int64 ( a) if * point < 0 => {
96- round_integer_scalar ! ( a, point, ScalarValue :: Int64 , i64 )
128+ round_integer_scalar ! ( a, point, ScalarValue :: Int64 , i64 , fail_on_error )
97129 }
98130 ScalarValue :: Int32 ( a) if * point < 0 => {
99- round_integer_scalar ! ( a, point, ScalarValue :: Int32 , i32 )
131+ round_integer_scalar ! ( a, point, ScalarValue :: Int32 , i32 , fail_on_error )
100132 }
101133 ScalarValue :: Int16 ( a) if * point < 0 => {
102- round_integer_scalar ! ( a, point, ScalarValue :: Int16 , i16 )
134+ round_integer_scalar ! ( a, point, ScalarValue :: Int16 , i16 , fail_on_error )
103135 }
104136 ScalarValue :: Int8 ( a) if * point < 0 => {
105- round_integer_scalar ! ( a, point, ScalarValue :: Int8 , i8 )
137+ round_integer_scalar ! ( a, point, ScalarValue :: Int8 , i8 , fail_on_error )
106138 }
107139 ScalarValue :: Decimal128 ( a, _, scale) if * scale >= 0 => {
108140 let f = decimal_round_f ( scale, point) ;
@@ -158,7 +190,7 @@ mod test {
158190 ] ) ) ) ,
159191 ColumnarValue :: Scalar ( ScalarValue :: Int64 ( Some ( 2 ) ) ) ,
160192 ] ;
161- let ColumnarValue :: Array ( result) = spark_round ( & args, & DataType :: Float32 ) ? else {
193+ let ColumnarValue :: Array ( result) = spark_round ( & args, & DataType :: Float32 , false ) ? else {
162194 unreachable ! ( )
163195 } ;
164196 let floats = as_float32_array ( & result) ?;
@@ -176,7 +208,7 @@ mod test {
176208 ] ) ) ) ,
177209 ColumnarValue :: Scalar ( ScalarValue :: Int64 ( Some ( 2 ) ) ) ,
178210 ] ;
179- let ColumnarValue :: Array ( result) = spark_round ( & args, & DataType :: Float64 ) ? else {
211+ let ColumnarValue :: Array ( result) = spark_round ( & args, & DataType :: Float64 , false ) ? else {
180212 unreachable ! ( )
181213 } ;
182214 let floats = as_float64_array ( & result) ?;
@@ -193,7 +225,7 @@ mod test {
193225 ColumnarValue :: Scalar ( ScalarValue :: Int64 ( Some ( 2 ) ) ) ,
194226 ] ;
195227 let ColumnarValue :: Scalar ( ScalarValue :: Float32 ( Some ( result) ) ) =
196- spark_round ( & args, & DataType :: Float32 ) ?
228+ spark_round ( & args, & DataType :: Float32 , false ) ?
197229 else {
198230 unreachable ! ( )
199231 } ;
@@ -209,7 +241,7 @@ mod test {
209241 ColumnarValue :: Scalar ( ScalarValue :: Int64 ( Some ( 2 ) ) ) ,
210242 ] ;
211243 let ColumnarValue :: Scalar ( ScalarValue :: Float64 ( Some ( result) ) ) =
212- spark_round ( & args, & DataType :: Float64 ) ?
244+ spark_round ( & args, & DataType :: Float64 , false ) ?
213245 else {
214246 unreachable ! ( )
215247 } ;
0 commit comments