@@ -11256,7 +11256,7 @@ impl<'a> Parser<'a> {
1125611256 if self.consume_token(&Token::LParen) {
1125711257 let precision = self.parse_literal_uint()?;
1125811258 let scale = if self.consume_token(&Token::Comma) {
11259- Some(self.parse_literal_uint ()?)
11259+ Some(self.parse_signed_integer ()?)
1126011260 } else {
1126111261 None
1126211262 };
@@ -11272,6 +11272,27 @@ impl<'a> Parser<'a> {
1127211272 }
1127311273 }
1127411274
11275+ /// Parse an optionally signed integer literal.
11276+ fn parse_signed_integer(&mut self) -> Result<i64, ParserError> {
11277+ let is_negative = self.consume_token(&Token::Minus);
11278+
11279+ if !is_negative {
11280+ let _ = self.consume_token(&Token::Plus);
11281+ }
11282+
11283+ let current_token = self.peek_token_ref();
11284+ match ¤t_token.token {
11285+ Token::Number(s, _) => {
11286+ let s = s.clone();
11287+ let span_start = current_token.span.start;
11288+ self.advance_token();
11289+ let value = Self::parse::<i64>(s, span_start)?;
11290+ Ok(if is_negative { -value } else { value })
11291+ }
11292+ _ => self.expected_ref("number", current_token),
11293+ }
11294+ }
11295+
1127511296 pub fn parse_optional_type_modifiers(&mut self) -> Result<Option<Vec<String>>, ParserError> {
1127611297 if self.consume_token(&Token::LParen) {
1127711298 let mut modifiers = Vec::new();
@@ -17118,7 +17139,7 @@ mod tests {
1711817139 use crate::ast::{
1711917140 CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
1712017141 };
17121- use crate::dialect::{AnsiDialect, GenericDialect};
17142+ use crate::dialect::{AnsiDialect, GenericDialect, PostgreSqlDialect };
1712217143 use crate::test_utils::TestedDialects;
1712317144
1712417145 macro_rules! test_parse_data_type {
@@ -17324,8 +17345,11 @@ mod tests {
1732417345 #[test]
1732517346 fn test_ansii_exact_numeric_types() {
1732617347 // Exact numeric types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type>
17327- let dialect =
17328- TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})]);
17348+ let dialect = TestedDialects::new(vec![
17349+ Box::new(GenericDialect {}),
17350+ Box::new(AnsiDialect {}),
17351+ Box::new(PostgreSqlDialect {}),
17352+ ]);
1732917353
1733017354 test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None));
1733117355
@@ -17368,6 +17392,53 @@ mod tests {
1736817392 "DEC(2,10)",
1736917393 DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10))
1737017394 );
17395+
17396+ // Test negative scale values.
17397+ test_parse_data_type!(
17398+ dialect,
17399+ "NUMERIC(10,-2)",
17400+ DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -2))
17401+ );
17402+
17403+ test_parse_data_type!(
17404+ dialect,
17405+ "DECIMAL(1000,-10)",
17406+ DataType::Decimal(ExactNumberInfo::PrecisionAndScale(1000, -10))
17407+ );
17408+
17409+ test_parse_data_type!(
17410+ dialect,
17411+ "DEC(5,-1000)",
17412+ DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -1000))
17413+ );
17414+
17415+ test_parse_data_type!(
17416+ dialect,
17417+ "NUMERIC(10,-5)",
17418+ DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -5))
17419+ );
17420+
17421+ test_parse_data_type!(
17422+ dialect,
17423+ "DECIMAL(20,-10)",
17424+ DataType::Decimal(ExactNumberInfo::PrecisionAndScale(20, -10))
17425+ );
17426+
17427+ test_parse_data_type!(
17428+ dialect,
17429+ "DEC(5,-2)",
17430+ DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -2))
17431+ );
17432+
17433+ dialect.run_parser_method("NUMERIC(10,+5)", |parser| {
17434+ let data_type = parser.parse_data_type().unwrap();
17435+ assert_eq!(
17436+ DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, 5)),
17437+ data_type
17438+ );
17439+ // Note: Explicit '+' sign is not preserved in output, which is correct
17440+ assert_eq!("NUMERIC(10,5)", data_type.to_string());
17441+ });
1737117442 }
1737217443
1737317444 #[test]
0 commit comments