iffyio commented on code in PR #1990: URL: https://github.com/apache/datafusion-sqlparser-rs/pull/1990#discussion_r2249929072
########## src/parser/mod.rs: ########## @@ -11229,6 +11229,38 @@ impl<'a> Parser<'a> { } } + /// Parse a scale value for NUMERIC/DECIMAL data types. + /// + /// Supports positive, negative, and explicitly positive (with `+`) scale values. + /// Negative scale values are particularly useful for PostgreSQL, where they indicate + /// rounding to the left of the decimal point. For example: + /// - `NUMERIC(5, 2)` stores up to 5 digits with 2 decimal places (e.g., 123.45) + /// - `NUMERIC(5, -2)` stores up to 5 digits rounded to hundreds (e.g., 12300) + fn parse_scale_value(&mut self) -> Result<i64, ParserError> { + let next_token = self.next_token(); + match next_token.token { + Token::Number(s, _) => Self::parse::<i64>(s, next_token.span.start), + Token::Minus => { + let next_token = self.next_token(); + match next_token.token { + Token::Number(s, _) => { + let positive_value = Self::parse::<i64>(s, next_token.span.start)?; + Ok(-positive_value) + } + _ => self.expected("number after minus", next_token), + } + } + Token::Plus => { + let next_token = self.next_token(); + match next_token.token { + Token::Number(s, _) => Self::parse::<i64>(s, next_token.span.start), + _ => self.expected("number after plus", next_token), + } + } + _ => self.expected("number", next_token), + } Review Comment: I think we might be able to simplify this to something like the following? ```rust if !self.consume_token(Token::Minus) { return i64::try_from(self.parse_literal_uint()?) } let next_token = self.next_token_ref(); match &next_token.token { Token::Number(s, _) => Self::parse::<i64>(s, next_token.span.start), _ => self.expected_ref("literal int", next_token), } ``` ########## src/parser/mod.rs: ########## @@ -11229,6 +11229,38 @@ impl<'a> Parser<'a> { } } + /// Parse a scale value for NUMERIC/DECIMAL data types. + /// + /// Supports positive, negative, and explicitly positive (with `+`) scale values. + /// Negative scale values are particularly useful for PostgreSQL, where they indicate + /// rounding to the left of the decimal point. For example: + /// - `NUMERIC(5, 2)` stores up to 5 digits with 2 decimal places (e.g., 123.45) + /// - `NUMERIC(5, -2)` stores up to 5 digits rounded to hundreds (e.g., 12300) + fn parse_scale_value(&mut self) -> Result<i64, ParserError> { Review Comment: ```suggestion /// Parse an optionally signed integer literal. fn parse_signed_integer(&mut self) -> Result<i64, ParserError> { ``` Think we can make the description and function name specific since it should be a straight-forward use case. ########## src/parser/mod.rs: ########## @@ -17319,6 +17351,75 @@ mod tests { "DEC(2,10)", DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10)) ); + + // Test negative scale values (PostgreSQL supports scale from -1000 to 1000) + test_parse_data_type!( + dialect, + "NUMERIC(10,-2)", + DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -2)) + ); + + test_parse_data_type!( + dialect, + "DECIMAL(1000,-10)", + DataType::Decimal(ExactNumberInfo::PrecisionAndScale(1000, -10)) + ); + + test_parse_data_type!( + dialect, + "DEC(5,-1000)", + DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -1000)) + ); + + // Test positive scale with explicit plus sign + dialect.run_parser_method("NUMERIC(10,+5)", |parser| { + let data_type = parser.parse_data_type().unwrap(); + assert_eq!( + DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, 5)), + data_type + ); + // Note: Explicit '+' sign is not preserved in output, which is correct + assert_eq!("NUMERIC(10,5)", data_type.to_string()); + }); + } + + #[test] + fn test_numeric_negative_scale() { + let dialect = TestedDialects::new(vec![ Review Comment: I think the negative test cases can be merged into `test_ansii_exact_numeric_types`? since they're the same feature. Also would let us avoid the duplicate tests between the two functions ########## src/parser/mod.rs: ########## @@ -17319,6 +17351,75 @@ mod tests { "DEC(2,10)", DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10)) ); + + // Test negative scale values (PostgreSQL supports scale from -1000 to 1000) Review Comment: ```suggestion // Test negative scale values. ``` we can skip the postgres comment since the parser doesnt treat it specially -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org For additional commands, e-mail: github-h...@datafusion.apache.org