@@ -2317,8 +2317,8 @@ fn cast_string_to_decimal256_impl(
23172317}
23182318
23192319/// Parse a string to decimal following Spark's behavior
2320- fn parse_string_to_decimal ( s : & str , precision : u8 , scale : i8 ) -> SparkResult < Option < i128 > > {
2321- let string_bytes = s . as_bytes ( ) ;
2320+ fn parse_string_to_decimal ( input_str : & str , precision : u8 , scale : i8 ) -> SparkResult < Option < i128 > > {
2321+ let string_bytes = input_str . as_bytes ( ) ;
23222322 let mut start = 0 ;
23232323 let mut end = string_bytes. len ( ) ;
23242324
@@ -2330,7 +2330,7 @@ fn parse_string_to_decimal(s: &str, precision: u8, scale: i8) -> SparkResult<Opt
23302330 end -= 1 ;
23312331 }
23322332
2333- let trimmed = & s [ start..end] ;
2333+ let trimmed = & input_str [ start..end] ;
23342334
23352335 if trimmed. is_empty ( ) {
23362336 return Ok ( None ) ;
@@ -2347,15 +2347,21 @@ fn parse_string_to_decimal(s: &str, precision: u8, scale: i8) -> SparkResult<Opt
23472347 return Ok ( None ) ;
23482348 }
23492349
2350- // validate and parse mantissa and exponent
2350+ // validate and parse mantissa and exponent or bubble up the error
23512351 let ( mantissa, exponent) = parse_decimal_str (
23522352 trimmed,
2353+ input_str,
23532354 "STRING" ,
23542355 & format ! ( "DECIMAL({},{})" , precision, scale) ,
23552356 ) ?;
23562357
2357- // return early when mantissa is 0
2358+ // Early return mantissa 0, Spark checks if it fits digits and throw error in ansi
23582359 if mantissa == 0 {
2360+ if exponent < -37 {
2361+ return Err ( SparkError :: NumericOutOfRange {
2362+ value : input_str. to_string ( ) ,
2363+ } ) ;
2364+ }
23592365 return Ok ( Some ( 0 ) ) ;
23602366 }
23612367
@@ -2424,10 +2430,15 @@ fn parse_string_to_decimal(s: &str, precision: u8, scale: i8) -> SparkResult<Opt
24242430}
24252431
24262432/// Parse a decimal string into mantissa and scale
2427- /// e.g., "123.45" -> (12345, 2), "-0.001" -> (-1, 3)
2428- fn parse_decimal_str ( s : & str , from_type : & str , to_type : & str ) -> SparkResult < ( i128 , i32 ) > {
2433+ /// e.g., "123.45" -> (12345, 2), "-0.001" -> (-1, 3) , 0e50 -> (0,50) etc
2434+ fn parse_decimal_str (
2435+ s : & str ,
2436+ original_str : & str ,
2437+ from_type : & str ,
2438+ to_type : & str ,
2439+ ) -> SparkResult < ( i128 , i32 ) > {
24292440 if s. is_empty ( ) {
2430- return Err ( invalid_value ( s , from_type, to_type) ) ;
2441+ return Err ( invalid_value ( original_str , from_type, to_type) ) ;
24312442 }
24322443
24332444 let ( mantissa_str, exponent) = if let Some ( e_pos) = s. find ( |c| [ 'e' , 'E' ] . contains ( & c) ) {
@@ -2436,7 +2447,7 @@ fn parse_decimal_str(s: &str, from_type: &str, to_type: &str) -> SparkResult<(i1
24362447 // Parse exponent
24372448 let exp: i32 = exponent_part
24382449 . parse ( )
2439- . map_err ( |_| invalid_value ( s , from_type, to_type) ) ?;
2450+ . map_err ( |_| invalid_value ( original_str , from_type, to_type) ) ?;
24402451
24412452 ( mantissa_part, exp)
24422453 } else {
@@ -2451,29 +2462,29 @@ fn parse_decimal_str(s: &str, from_type: &str, to_type: &str) -> SparkResult<(i1
24512462 } ;
24522463
24532464 if mantissa_str. starts_with ( '+' ) || mantissa_str. starts_with ( '-' ) {
2454- return Err ( invalid_value ( s , from_type, to_type) ) ;
2465+ return Err ( invalid_value ( original_str , from_type, to_type) ) ;
24552466 }
24562467
24572468 let ( integral_part, fractional_part) = match mantissa_str. find ( '.' ) {
24582469 Some ( dot_pos) => {
24592470 if mantissa_str[ dot_pos + 1 ..] . contains ( '.' ) {
2460- return Err ( invalid_value ( s , from_type, to_type) ) ;
2471+ return Err ( invalid_value ( original_str , from_type, to_type) ) ;
24612472 }
24622473 ( & mantissa_str[ ..dot_pos] , & mantissa_str[ dot_pos + 1 ..] )
24632474 }
24642475 None => ( mantissa_str, "" ) ,
24652476 } ;
24662477
24672478 if integral_part. is_empty ( ) && fractional_part. is_empty ( ) {
2468- return Err ( invalid_value ( s , from_type, to_type) ) ;
2479+ return Err ( invalid_value ( original_str , from_type, to_type) ) ;
24692480 }
24702481
24712482 if !integral_part. is_empty ( ) && !integral_part. bytes ( ) . all ( |b| b. is_ascii_digit ( ) ) {
2472- return Err ( invalid_value ( s , from_type, to_type) ) ;
2483+ return Err ( invalid_value ( original_str , from_type, to_type) ) ;
24732484 }
24742485
24752486 if !fractional_part. is_empty ( ) && !fractional_part. bytes ( ) . all ( |b| b. is_ascii_digit ( ) ) {
2476- return Err ( invalid_value ( s , from_type, to_type) ) ;
2487+ return Err ( invalid_value ( original_str , from_type, to_type) ) ;
24772488 }
24782489
24792490 // Parse integral part
@@ -2483,7 +2494,7 @@ fn parse_decimal_str(s: &str, from_type: &str, to_type: &str) -> SparkResult<(i1
24832494 } else {
24842495 integral_part
24852496 . parse ( )
2486- . map_err ( |_| invalid_value ( s , from_type, to_type) ) ?
2497+ . map_err ( |_| invalid_value ( original_str , from_type, to_type) ) ?
24872498 } ;
24882499
24892500 // Parse fractional part
@@ -2493,14 +2504,14 @@ fn parse_decimal_str(s: &str, from_type: &str, to_type: &str) -> SparkResult<(i1
24932504 } else {
24942505 fractional_part
24952506 . parse ( )
2496- . map_err ( |_| invalid_value ( s , from_type, to_type) ) ?
2507+ . map_err ( |_| invalid_value ( original_str , from_type, to_type) ) ?
24972508 } ;
24982509
24992510 // Combine: value = integral * 10^fractional_scale + fractional
25002511 let mantissa = integral_value
25012512 . checked_mul ( 10_i128 . pow ( fractional_scale as u32 ) )
25022513 . and_then ( |v| v. checked_add ( fractional_value) )
2503- . ok_or_else ( || invalid_value ( s , from_type, to_type) ) ?;
2514+ . ok_or_else ( || invalid_value ( original_str , from_type, to_type) ) ?;
25042515
25052516 let final_mantissa = if negative { -mantissa } else { mantissa } ;
25062517 // final scale = fractional_scale - exponent
0 commit comments