@@ -11256,7 +11256,7 @@ impl<'a> Parser<'a> {
11256
11256
if self.consume_token(&Token::LParen) {
11257
11257
let precision = self.parse_literal_uint()?;
11258
11258
let scale = if self.consume_token(&Token::Comma) {
11259
- Some(self.parse_literal_uint ()?)
11259
+ Some(self.parse_signed_integer ()?)
11260
11260
} else {
11261
11261
None
11262
11262
};
@@ -11272,6 +11272,27 @@ impl<'a> Parser<'a> {
11272
11272
}
11273
11273
}
11274
11274
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
+
11275
11296
pub fn parse_optional_type_modifiers(&mut self) -> Result<Option<Vec<String>>, ParserError> {
11276
11297
if self.consume_token(&Token::LParen) {
11277
11298
let mut modifiers = Vec::new();
@@ -17118,7 +17139,7 @@ mod tests {
17118
17139
use crate::ast::{
17119
17140
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
17120
17141
};
17121
- use crate::dialect::{AnsiDialect, GenericDialect};
17142
+ use crate::dialect::{AnsiDialect, GenericDialect, PostgreSqlDialect };
17122
17143
use crate::test_utils::TestedDialects;
17123
17144
17124
17145
macro_rules! test_parse_data_type {
@@ -17324,8 +17345,11 @@ mod tests {
17324
17345
#[test]
17325
17346
fn test_ansii_exact_numeric_types() {
17326
17347
// 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
+ ]);
17329
17353
17330
17354
test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None));
17331
17355
@@ -17368,6 +17392,53 @@ mod tests {
17368
17392
"DEC(2,10)",
17369
17393
DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10))
17370
17394
);
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
+ });
17371
17442
}
17372
17443
17373
17444
#[test]
0 commit comments