mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
Return errors, not panic, when integers fail to parse in AUTO_INCREMENT
and TOP
(#1305)
This commit is contained in:
parent
345e2098fb
commit
79af31b672
2 changed files with 40 additions and 15 deletions
|
@ -20,7 +20,10 @@ use alloc::{
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::fmt;
|
use core::{
|
||||||
|
fmt::{self, Display},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
|
@ -3260,6 +3263,18 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse<T: FromStr>(s: String, loc: Location) -> Result<T, ParserError>
|
||||||
|
where
|
||||||
|
<T as FromStr>::Err: Display,
|
||||||
|
{
|
||||||
|
s.parse::<T>().map_err(|e| {
|
||||||
|
ParserError::ParserError(format!(
|
||||||
|
"Could not parse '{s}' as {}: {e}{loc}",
|
||||||
|
core::any::type_name::<T>()
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a comma-separated list of 1+ SelectItem
|
/// Parse a comma-separated list of 1+ SelectItem
|
||||||
pub fn parse_projection(&mut self) -> Result<Vec<SelectItem>, ParserError> {
|
pub fn parse_projection(&mut self) -> Result<Vec<SelectItem>, ParserError> {
|
||||||
// BigQuery and Snowflake allow trailing commas, but only in project lists
|
// BigQuery and Snowflake allow trailing commas, but only in project lists
|
||||||
|
@ -5281,7 +5296,7 @@ impl<'a> Parser<'a> {
|
||||||
let _ = self.consume_token(&Token::Eq);
|
let _ = self.consume_token(&Token::Eq);
|
||||||
let next_token = self.next_token();
|
let next_token = self.next_token();
|
||||||
match next_token.token {
|
match next_token.token {
|
||||||
Token::Number(s, _) => Some(s.parse::<u32>().expect("literal int")),
|
Token::Number(s, _) => Some(Self::parse::<u32>(s, next_token.location)?),
|
||||||
_ => self.expected("literal int", next_token)?,
|
_ => self.expected("literal int", next_token)?,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -6725,10 +6740,7 @@ impl<'a> Parser<'a> {
|
||||||
// The call to n.parse() returns a bigdecimal when the
|
// The call to n.parse() returns a bigdecimal when the
|
||||||
// bigdecimal feature is enabled, and is otherwise a no-op
|
// bigdecimal feature is enabled, and is otherwise a no-op
|
||||||
// (i.e., it returns the input string).
|
// (i.e., it returns the input string).
|
||||||
Token::Number(ref n, l) => match n.parse() {
|
Token::Number(n, l) => Ok(Value::Number(Self::parse(n, location)?, l)),
|
||||||
Ok(n) => Ok(Value::Number(n, l)),
|
|
||||||
Err(e) => parser_err!(format!("Could not parse '{n}' as number: {e}"), location),
|
|
||||||
},
|
|
||||||
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
|
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
|
||||||
Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())),
|
Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())),
|
||||||
Token::TripleSingleQuotedString(ref s) => {
|
Token::TripleSingleQuotedString(ref s) => {
|
||||||
|
@ -6820,9 +6832,7 @@ impl<'a> Parser<'a> {
|
||||||
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
|
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
|
||||||
let next_token = self.next_token();
|
let next_token = self.next_token();
|
||||||
match next_token.token {
|
match next_token.token {
|
||||||
Token::Number(s, _) => s.parse::<u64>().map_err(|e| {
|
Token::Number(s, _) => Self::parse::<u64>(s, next_token.location),
|
||||||
ParserError::ParserError(format!("Could not parse '{s}' as u64: {e}"))
|
|
||||||
}),
|
|
||||||
_ => self.expected("literal int", next_token),
|
_ => self.expected("literal int", next_token),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9273,7 +9283,7 @@ impl<'a> Parser<'a> {
|
||||||
return self.expected("literal number", next_token);
|
return self.expected("literal number", next_token);
|
||||||
};
|
};
|
||||||
self.expect_token(&Token::RBrace)?;
|
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) => {
|
Token::Number(n, _) if self.consume_token(&Token::Comma) => {
|
||||||
let next_token = self.next_token();
|
let next_token = self.next_token();
|
||||||
|
@ -9281,12 +9291,12 @@ impl<'a> Parser<'a> {
|
||||||
Token::Number(m, _) => {
|
Token::Number(m, _) => {
|
||||||
self.expect_token(&Token::RBrace)?;
|
self.expect_token(&Token::RBrace)?;
|
||||||
RepetitionQuantifier::Range(
|
RepetitionQuantifier::Range(
|
||||||
n.parse().expect("literal int"),
|
Self::parse(n, token.location)?,
|
||||||
m.parse().expect("literal int"),
|
Self::parse(m, token.location)?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Token::RBrace => {
|
Token::RBrace => {
|
||||||
RepetitionQuantifier::AtLeast(n.parse().expect("literal int"))
|
RepetitionQuantifier::AtLeast(Self::parse(n, token.location)?)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return self.expected("} or upper bound", next_token);
|
return self.expected("} or upper bound", next_token);
|
||||||
|
@ -9295,7 +9305,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Token::Number(n, _) => {
|
Token::Number(n, _) => {
|
||||||
self.expect_token(&Token::RBrace)?;
|
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),
|
_ => return self.expected("quantifier range", token),
|
||||||
}
|
}
|
||||||
|
@ -10329,7 +10339,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
let next_token = self.next_token();
|
let next_token = self.next_token();
|
||||||
let quantity = match next_token.token {
|
let quantity = match next_token.token {
|
||||||
Token::Number(s, _) => s.parse::<u64>().expect("literal int"),
|
Token::Number(s, _) => Self::parse::<u64>(s, next_token.location)?,
|
||||||
_ => self.expected("literal int", next_token)?,
|
_ => self.expected("literal int", next_token)?,
|
||||||
};
|
};
|
||||||
Some(TopQuantity::Constant(quantity))
|
Some(TopQuantity::Constant(quantity))
|
||||||
|
|
|
@ -10006,3 +10006,18 @@ fn parse_select_wildcard_with_except() {
|
||||||
"sql parser error: Expected identifier, found: )"
|
"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:?}");
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue