@@ -11287,7 +11287,7 @@ impl<'a> Parser<'a> {
1128711287 if self.consume_token(&Token::LParen) {
1128811288 let precision = self.parse_literal_uint()?;
1128911289 let scale = if self.consume_token(&Token::Comma) {
11290- Some(self.parse_literal_uint ()?)
11290+ Some(self.parse_signed_integer ()?)
1129111291 } else {
1129211292 None
1129311293 };
@@ -11303,6 +11303,27 @@ impl<'a> Parser<'a> {
1130311303 }
1130411304 }
1130511305
11306+ /// Parse an optionally signed integer literal.
11307+ fn parse_signed_integer(&mut self) -> Result<i64, ParserError> {
11308+ let is_negative = self.consume_token(&Token::Minus);
11309+
11310+ if !is_negative {
11311+ let _ = self.consume_token(&Token::Plus);
11312+ }
11313+
11314+ let current_token = self.peek_token_ref();
11315+ match ¤t_token.token {
11316+ Token::Number(s, _) => {
11317+ let s = s.clone();
11318+ let span_start = current_token.span.start;
11319+ self.advance_token();
11320+ let value = Self::parse::<i64>(s, span_start)?;
11321+ Ok(if is_negative { -value } else { value })
11322+ }
11323+ _ => self.expected_ref("number", current_token),
11324+ }
11325+ }
11326+
1130611327 pub fn parse_optional_type_modifiers(&mut self) -> Result<Option<Vec<String>>, ParserError> {
1130711328 if self.consume_token(&Token::LParen) {
1130811329 let mut modifiers = Vec::new();
@@ -17150,7 +17171,7 @@ mod tests {
1715017171 use crate::ast::{
1715117172 CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
1715217173 };
17153- use crate::dialect::{AnsiDialect, GenericDialect};
17174+ use crate::dialect::{AnsiDialect, GenericDialect, PostgreSqlDialect };
1715417175 use crate::test_utils::TestedDialects;
1715517176
1715617177 macro_rules! test_parse_data_type {
@@ -17356,8 +17377,11 @@ mod tests {
1735617377 #[test]
1735717378 fn test_ansii_exact_numeric_types() {
1735817379 // Exact numeric types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type>
17359- let dialect =
17360- TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})]);
17380+ let dialect = TestedDialects::new(vec![
17381+ Box::new(GenericDialect {}),
17382+ Box::new(AnsiDialect {}),
17383+ Box::new(PostgreSqlDialect {}),
17384+ ]);
1736117385
1736217386 test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None));
1736317387
@@ -17400,6 +17424,53 @@ mod tests {
1740017424 "DEC(2,10)",
1740117425 DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10))
1740217426 );
17427+
17428+ // Test negative scale values.
17429+ test_parse_data_type!(
17430+ dialect,
17431+ "NUMERIC(10,-2)",
17432+ DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -2))
17433+ );
17434+
17435+ test_parse_data_type!(
17436+ dialect,
17437+ "DECIMAL(1000,-10)",
17438+ DataType::Decimal(ExactNumberInfo::PrecisionAndScale(1000, -10))
17439+ );
17440+
17441+ test_parse_data_type!(
17442+ dialect,
17443+ "DEC(5,-1000)",
17444+ DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -1000))
17445+ );
17446+
17447+ test_parse_data_type!(
17448+ dialect,
17449+ "NUMERIC(10,-5)",
17450+ DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -5))
17451+ );
17452+
17453+ test_parse_data_type!(
17454+ dialect,
17455+ "DECIMAL(20,-10)",
17456+ DataType::Decimal(ExactNumberInfo::PrecisionAndScale(20, -10))
17457+ );
17458+
17459+ test_parse_data_type!(
17460+ dialect,
17461+ "DEC(5,-2)",
17462+ DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -2))
17463+ );
17464+
17465+ dialect.run_parser_method("NUMERIC(10,+5)", |parser| {
17466+ let data_type = parser.parse_data_type().unwrap();
17467+ assert_eq!(
17468+ DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, 5)),
17469+ data_type
17470+ );
17471+ // Note: Explicit '+' sign is not preserved in output, which is correct
17472+ assert_eq!("NUMERIC(10,5)", data_type.to_string());
17473+ });
1740317474 }
1740417475
1740517476 #[test]
0 commit comments