@@ -836,8 +836,10 @@ fn parse_e_notation<T: DecimalType>(
836836
837837/// Parse the string format decimal value to i128/i256 format and checking the precision and scale.
838838/// Expected behavior:
839- /// - the result value can't be out of bounds.
840- /// - when parsing a decimal with scale 0, any digits pass the decimal point will be discarded
839+ /// - The result value can't be out of bounds.
840+ /// - When parsing a decimal with scale 0, all fractional digits will be discarded. The final
841+ /// fractional digits may be a subset or a superset of the digits after the decimal point when
842+ /// e-notation is used.
841843pub fn parse_decimal < T : DecimalType > (
842844 s : & str ,
843845 precision : u8 ,
@@ -848,19 +850,19 @@ pub fn parse_decimal<T: DecimalType>(
848850 let mut digits: u8 = 0 ;
849851 let base = T :: Native :: usize_as ( 10 ) ;
850852
853+ if matches ! ( s, "" | "-" | "+" | "." | "1e" | "1e+" | "1e-" ) {
854+ return Err ( ArrowError :: ParseError ( format ! (
855+ "can't parse the string value {s} to decimal"
856+ ) ) ) ;
857+ }
858+
851859 let bs = s. as_bytes ( ) ;
852860 let ( signed, negative) = match bs. first ( ) {
853861 Some ( b'-' ) => ( true , true ) ,
854862 Some ( b'+' ) => ( true , false ) ,
855863 _ => ( false , false ) ,
856864 } ;
857865
858- if bs. is_empty ( ) || signed && bs. len ( ) == 1 {
859- return Err ( ArrowError :: ParseError ( format ! (
860- "can't parse the string value {s} to decimal"
861- ) ) ) ;
862- }
863-
864866 // Iterate over the raw input bytes, skipping the sign if any
865867 let mut bs = bs. iter ( ) . enumerate ( ) . skip ( signed as usize ) ;
866868
@@ -918,13 +920,6 @@ pub fn parse_decimal<T: DecimalType>(
918920 if is_e_notation {
919921 break ;
920922 }
921-
922- // Fail on "."
923- if digits == 0 && scale != 0 {
924- return Err ( ArrowError :: ParseError ( format ! (
925- "can't parse the string value {s} to decimal"
926- ) ) ) ;
927- }
928923 }
929924 b'e' | b'E' => {
930925 result = parse_e_notation :: < T > (
@@ -2600,6 +2595,9 @@ mod tests {
26002595 "1.1e.12" ,
26012596 "1.23e+3." ,
26022597 "1.23e+3.1" ,
2598+ "1e" ,
2599+ "1e+" ,
2600+ "1e-" ,
26032601 ] ;
26042602 for s in can_not_parse_tests {
26052603 let result_128 = parse_decimal :: < Decimal128Type > ( s, 20 , 3 ) ;
@@ -2742,6 +2740,7 @@ mod tests {
27422740 }
27432741
27442742 let zero_scale_tests = [
2743+ ( ".123" , 0 , 3 ) ,
27452744 ( "0.123" , 0 , 3 ) ,
27462745 ( "1.0" , 1 , 3 ) ,
27472746 ( "1.2" , 1 , 3 ) ,
@@ -2769,6 +2768,15 @@ mod tests {
27692768 let result_128 = parse_decimal :: < Decimal128Type > ( s, precision, 0 ) . unwrap ( ) ;
27702769 assert_eq ! ( i, result_128) ;
27712770 }
2771+
2772+ let can_not_parse_zero_scale = [ "." , "blag" , "" , "+" , "-" , "e" ] ;
2773+ for s in can_not_parse_zero_scale {
2774+ let result_128 = parse_decimal :: < Decimal128Type > ( s, 5 , 0 ) ;
2775+ assert_eq ! (
2776+ format!( "Parser error: can't parse the string value {s} to decimal" ) ,
2777+ result_128. unwrap_err( ) . to_string( ) ,
2778+ ) ;
2779+ }
27722780 }
27732781
27742782 #[ test]
0 commit comments