From 0019be9234efb058877776281a6bbfc8d16f554b Mon Sep 17 00:00:00 2001 From: Emil Ejbyfeldt Date: Mon, 10 Jun 2024 20:54:43 +0200 Subject: [PATCH 1/4] Return error when AUTO_INCREMENT offset is too large Closes #1303 --- src/parser/mod.rs | 7 ++++++- tests/sqlparser_common.rs | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index c591b8116..8d524ea46 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -5281,7 +5281,12 @@ impl<'a> Parser<'a> { let _ = self.consume_token(&Token::Eq); let next_token = self.next_token(); match next_token.token { - Token::Number(s, _) => Some(s.parse::().expect("literal int")), + Token::Number(s, _) => Some(s.parse::().map_err(|e| { + ParserError::ParserError(format!( + "Could not parse '{s}' as u32: {e}{}", + next_token.location + )) + })?), _ => self.expected("literal int", next_token)?, } } else { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index f6518e276..fed61576a 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -9991,3 +9991,18 @@ fn parse_select_wildcard_with_except() { "sql parser error: Expected identifier, found: )" ); } + +#[test] +fn parse_auto_increment_too_large() { + let dialect = GenericDialect {}; + let u64_max = u64::MAX; + let sql = + format!("CREATE TABLE foo (bar INT NOT NULL AUTO_INCREMENT) AUTO_INCREMENT=1{u64_max}"); + + let res = Parser::new(&dialect) + .try_with_sql(&sql) + .expect("tokenize to work") + .parse_statements(); + + assert!(res.is_err(), "{res:?}"); +} From 5540ff035e2b88db674a133157dda3c36b2e57d1 Mon Sep 17 00:00:00 2001 From: Emil Ejbyfeldt Date: Mon, 10 Jun 2024 21:44:27 +0200 Subject: [PATCH 2/4] Fix one more case of int failure --- src/parser/mod.rs | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8d524ea46..1fe25f158 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -20,7 +20,10 @@ use alloc::{ vec, vec::Vec, }; -use core::fmt; +use core::{ + fmt::{self, Display}, + str::FromStr, +}; use log::debug; @@ -3260,6 +3263,18 @@ impl<'a> Parser<'a> { } } + fn parse(s: String, loc: Location) -> Result + where + ::Err: Display, + { + s.parse::().map_err(|e| { + ParserError::ParserError(format!( + "Could not parse '{s}' as {}: {e}{loc}", + std::any::type_name::() + )) + }) + } + /// Parse a comma-separated list of 1+ SelectItem pub fn parse_projection(&mut self) -> Result, ParserError> { // BigQuery and Snowflake allow trailing commas, but only in project lists @@ -5281,12 +5296,7 @@ impl<'a> Parser<'a> { let _ = self.consume_token(&Token::Eq); let next_token = self.next_token(); match next_token.token { - Token::Number(s, _) => Some(s.parse::().map_err(|e| { - ParserError::ParserError(format!( - "Could not parse '{s}' as u32: {e}{}", - next_token.location - )) - })?), + Token::Number(s, _) => Some(Self::parse::(s, next_token.location)?), _ => self.expected("literal int", next_token)?, } } else { @@ -6730,10 +6740,7 @@ impl<'a> Parser<'a> { // The call to n.parse() returns a bigdecimal when the // bigdecimal feature is enabled, and is otherwise a no-op // (i.e., it returns the input string). - Token::Number(ref n, l) => match n.parse() { - Ok(n) => Ok(Value::Number(n, l)), - Err(e) => parser_err!(format!("Could not parse '{n}' as number: {e}"), location), - }, + Token::Number(n, l) => Ok(Value::Number(Self::parse(n, location)?, l)), Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())), Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())), Token::TripleSingleQuotedString(ref s) => { @@ -6825,9 +6832,7 @@ impl<'a> Parser<'a> { pub fn parse_literal_uint(&mut self) -> Result { let next_token = self.next_token(); match next_token.token { - Token::Number(s, _) => s.parse::().map_err(|e| { - ParserError::ParserError(format!("Could not parse '{s}' as u64: {e}")) - }), + Token::Number(s, _) => Self::parse::(s, next_token.location), _ => self.expected("literal int", next_token), } } @@ -10331,7 +10336,7 @@ impl<'a> Parser<'a> { } else { let next_token = self.next_token(); let quantity = match next_token.token { - Token::Number(s, _) => s.parse::().expect("literal int"), + Token::Number(s, _) => Self::parse::(s, next_token.location)?, _ => self.expected("literal int", next_token)?, }; Some(TopQuantity::Constant(quantity)) From cd8a7d517f534c8b3dfe31b0064f88e3c8ae9a58 Mon Sep 17 00:00:00 2001 From: Emil Ejbyfeldt Date: Mon, 10 Jun 2024 21:58:03 +0200 Subject: [PATCH 3/4] Fix more parsing hard failures --- src/parser/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1fe25f158..2a2b2466c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -9292,7 +9292,7 @@ impl<'a> Parser<'a> { return self.expected("literal number", next_token); }; self.expect_token(&Token::RBrace)?; - RepetitionQuantifier::AtMost(n.parse().expect("literal int")) + RepetitionQuantifier::AtMost(Self::parse(n, token.location)?) } Token::Number(n, _) if self.consume_token(&Token::Comma) => { let next_token = self.next_token(); @@ -9300,12 +9300,12 @@ impl<'a> Parser<'a> { Token::Number(m, _) => { self.expect_token(&Token::RBrace)?; RepetitionQuantifier::Range( - n.parse().expect("literal int"), - m.parse().expect("literal int"), + Self::parse(n, token.location)?, + Self::parse(m, token.location)?, ) } Token::RBrace => { - RepetitionQuantifier::AtLeast(n.parse().expect("literal int")) + RepetitionQuantifier::AtLeast(Self::parse(n, token.location)?) } _ => { return self.expected("} or upper bound", next_token); @@ -9314,7 +9314,7 @@ impl<'a> Parser<'a> { } Token::Number(n, _) => { self.expect_token(&Token::RBrace)?; - RepetitionQuantifier::Exactly(n.parse().expect("literal int")) + RepetitionQuantifier::Exactly(Self::parse(n, token.location)?) } _ => return self.expected("quantifier range", token), } From abe9442ff98db3dd6056804f7b2e5d77f30b09a0 Mon Sep 17 00:00:00 2001 From: Emil Ejbyfeldt Date: Tue, 18 Jun 2024 15:00:13 +0200 Subject: [PATCH 4/4] Use core instead of std --- src/parser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 2a2b2466c..10180406f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -3270,7 +3270,7 @@ impl<'a> Parser<'a> { s.parse::().map_err(|e| { ParserError::ParserError(format!( "Could not parse '{s}' as {}: {e}{loc}", - std::any::type_name::() + core::any::type_name::() )) }) }