@@ -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, "" | "-" | "+" | "." ) {
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 > (
@@ -2742,6 +2737,7 @@ mod tests {
27422737 }
27432738
27442739 let zero_scale_tests = [
2740+ ( ".123" , 0 , 3 ) ,
27452741 ( "0.123" , 0 , 3 ) ,
27462742 ( "1.0" , 1 , 3 ) ,
27472743 ( "1.2" , 1 , 3 ) ,
@@ -2769,6 +2765,15 @@ mod tests {
27692765 let result_128 = parse_decimal :: < Decimal128Type > ( s, precision, 0 ) . unwrap ( ) ;
27702766 assert_eq ! ( i, result_128) ;
27712767 }
2768+
2769+ let can_not_parse_zero_scale = [ "." , "blag" , "" , "+" , "-" , "e" ] ;
2770+ for s in can_not_parse_zero_scale {
2771+ let result_128 = parse_decimal :: < Decimal128Type > ( s, 5 , 0 ) ;
2772+ assert_eq ! (
2773+ format!( "Parser error: can't parse the string value {s} to decimal" ) ,
2774+ result_128. unwrap_err( ) . to_string( ) ,
2775+ ) ;
2776+ }
27722777 }
27732778
27742779 #[ test]
0 commit comments