@@ -19,8 +19,12 @@ use crate::utils::array_with_timezone;
1919use crate :: { timezone, BinaryOutputStyle } ;
2020use crate :: { EvalMode , SparkError , SparkResult } ;
2121use arrow:: array:: builder:: StringBuilder ;
22- use arrow:: array:: { DictionaryArray , GenericByteArray , StringArray , StructArray } ;
22+ use arrow:: array:: {
23+ ArrowNativeTypeOp , Decimal128Builder , DictionaryArray , GenericByteArray , StringArray ,
24+ StructArray ,
25+ } ;
2326use arrow:: compute:: can_cast_types;
27+ use arrow:: datatypes:: DataType :: Float32 ;
2428use arrow:: datatypes:: {
2529 ArrowDictionaryKeyType , ArrowNativeType , DataType , GenericBinaryType , Schema ,
2630} ;
@@ -41,15 +45,17 @@ use arrow::{
4145 record_batch:: RecordBatch ,
4246 util:: display:: FormatOptions ,
4347} ;
48+ use base64:: prelude:: * ;
4449use chrono:: { DateTime , NaiveDate , TimeZone , Timelike } ;
4550use datafusion:: common:: {
4651 cast:: as_generic_string_array, internal_err, DataFusionError , Result as DataFusionResult ,
4752 ScalarValue ,
4853} ;
4954use datafusion:: physical_expr:: PhysicalExpr ;
5055use datafusion:: physical_plan:: ColumnarValue ;
56+ use futures:: future:: err;
5157use num:: {
52- cast:: AsPrimitive , integer:: div_floor, traits:: CheckedNeg , CheckedSub , Integer , Num ,
58+ cast:: AsPrimitive , integer:: div_floor, traits:: CheckedNeg , CheckedSub , Integer , Num , Signed ,
5359 ToPrimitive ,
5460} ;
5561use regex:: Regex ;
@@ -62,8 +68,6 @@ use std::{
6268 sync:: Arc ,
6369} ;
6470
65- use base64:: prelude:: * ;
66-
6771static TIMESTAMP_FORMAT : Option < & str > = Some ( "%Y-%m-%d %H:%M:%S%.f" ) ;
6872
6973const MICROS_PER_SECOND : i64 = 1000000 ;
@@ -983,6 +987,9 @@ fn cast_array(
983987 {
984988 spark_cast_int_to_int ( & array, eval_mode, from_type, to_type)
985989 }
990+ ( Int8 | Int16 | Int32 | Int64 , Decimal128 ( precision, scale) ) => {
991+ cast_int_to_decimal128 ( & array, eval_mode, from_type, to_type, * precision, * scale)
992+ }
986993 ( Utf8 , Int8 | Int16 | Int32 | Int64 ) => {
987994 cast_string_to_int :: < i32 > ( to_type, & array, eval_mode)
988995 }
@@ -1464,6 +1471,106 @@ where
14641471 cast_float_to_string ! ( from, _eval_mode, f32 , Float32Array , OffsetSize )
14651472}
14661473
1474+ fn cast_int_to_decimal128_internal < T > (
1475+ array : & PrimitiveArray < T > ,
1476+ precision : u8 ,
1477+ scale : i8 ,
1478+ eval_mode : EvalMode ,
1479+ ) -> SparkResult < ArrayRef >
1480+ where
1481+ T : ArrowPrimitiveType ,
1482+ T :: Native : Into < i128 > ,
1483+ {
1484+ let mut builder = Decimal128Builder :: with_capacity ( array. len ( ) ) ;
1485+ let multiplier = 10_i128 . pow ( scale as u32 ) ;
1486+
1487+ for i in 0 ..array. len ( ) {
1488+ if array. is_null ( i) {
1489+ builder. append_null ( ) ;
1490+ } else {
1491+ let v = array. value ( i) . into ( ) ;
1492+ let scaled = v. checked_mul ( multiplier) ;
1493+ match scaled {
1494+ Some ( scaled) => {
1495+ if !is_validate_decimal_precision ( scaled, precision) {
1496+ match eval_mode {
1497+ EvalMode :: Ansi => {
1498+ return Err ( SparkError :: NumericValueOutOfRange {
1499+ value : v. to_string ( ) ,
1500+ precision,
1501+ scale,
1502+ } ) ;
1503+ }
1504+ ( EvalMode :: Try | EvalMode :: Legacy ) => {
1505+ builder. append_null ( )
1506+ }
1507+ }
1508+ } else {
1509+ builder. append_value ( scaled) ;
1510+ }
1511+ }
1512+ _ => {
1513+ return Err ( SparkError :: NumericValueOutOfRange {
1514+ value : v. to_string ( ) ,
1515+ precision,
1516+ scale,
1517+ } )
1518+ }
1519+ }
1520+ }
1521+ }
1522+ Ok ( Arc :: new (
1523+ builder. with_precision_and_scale ( precision, scale) ?. finish ( ) ,
1524+ ) )
1525+ }
1526+ fn cast_int_to_decimal128 (
1527+ array : & dyn Array ,
1528+ eval_mode : EvalMode ,
1529+ from_type : & DataType ,
1530+ to_type : & DataType ,
1531+ precision : u8 ,
1532+ scale : i8 ,
1533+ ) -> SparkResult < ArrayRef > {
1534+ match ( from_type, to_type) {
1535+ ( DataType :: Int8 , DataType :: Decimal128 ( p, s) ) => {
1536+ cast_int_to_decimal128_internal :: < Int8Type > (
1537+ array. as_primitive :: < Int8Type > ( ) ,
1538+ precision,
1539+ scale,
1540+ eval_mode,
1541+ )
1542+ }
1543+ ( DataType :: Int16 , DataType :: Decimal128 ( p, s) ) => {
1544+ cast_int_to_decimal128_internal :: < Int16Type > (
1545+ array. as_primitive :: < Int16Type > ( ) ,
1546+ precision,
1547+ scale,
1548+ eval_mode,
1549+ )
1550+ }
1551+ ( DataType :: Int32 , DataType :: Decimal128 ( p, s) ) => {
1552+ cast_int_to_decimal128_internal :: < Int32Type > (
1553+ array. as_primitive :: < Int32Type > ( ) ,
1554+ precision,
1555+ scale,
1556+ eval_mode,
1557+ )
1558+ }
1559+ ( DataType :: Int64 , DataType :: Decimal128 ( p, s) ) => {
1560+ cast_int_to_decimal128_internal :: < Int64Type > (
1561+ array. as_primitive :: < Int64Type > ( ) ,
1562+ precision,
1563+ scale,
1564+ eval_mode,
1565+ )
1566+ }
1567+ _ => Err ( SparkError :: Internal ( format ! (
1568+ "Unsupported cast from datatype : {}" ,
1569+ from_type
1570+ ) ) ) ,
1571+ }
1572+ }
1573+
14671574fn spark_cast_int_to_int (
14681575 array : & dyn Array ,
14691576 eval_mode : EvalMode ,
0 commit comments