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

Reply via email to