mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-31 11:17:23 +00:00
Change Value::Long() to u64, use u64 instead of usize
The tokenizer emits a separate Token for +/- signs, so the value of Value::Long() (as well as of parse_literal_int()) may never be negative. Also we have been using both u64 and usize to represent a parsed unsigned number. Change to using u64 for consistency.
This commit is contained in:
parent
0407ed2b57
commit
d9edc2588b
4 changed files with 34 additions and 46 deletions
|
@ -1,26 +1,26 @@
|
|||
use super::SQLObjectName;
|
||||
|
||||
/// SQL datatypes for literals in SQL statements
|
||||
/// SQL data types
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SQLType {
|
||||
/// Fixed-length character type e.g. CHAR(10)
|
||||
Char(Option<usize>),
|
||||
Char(Option<u64>),
|
||||
/// Variable-length character type e.g. VARCHAR(10)
|
||||
Varchar(Option<usize>),
|
||||
Varchar(Option<u64>),
|
||||
/// Uuid type
|
||||
Uuid,
|
||||
/// Large character object e.g. CLOB(1000)
|
||||
Clob(usize),
|
||||
Clob(u64),
|
||||
/// Fixed-length binary type e.g. BINARY(10)
|
||||
Binary(usize),
|
||||
Binary(u64),
|
||||
/// Variable-length binary type e.g. VARBINARY(10)
|
||||
Varbinary(usize),
|
||||
Varbinary(u64),
|
||||
/// Large binary object e.g. BLOB(1000)
|
||||
Blob(usize),
|
||||
Blob(u64),
|
||||
/// Decimal type with optional precision and scale e.g. DECIMAL(10,2)
|
||||
Decimal(Option<usize>, Option<usize>),
|
||||
Decimal(Option<u64>, Option<u64>),
|
||||
/// Floating point with optional precision e.g. FLOAT(8)
|
||||
Float(Option<usize>),
|
||||
Float(Option<u64>),
|
||||
/// Small integer
|
||||
SmallInt,
|
||||
/// Integer
|
||||
|
@ -87,7 +87,7 @@ impl ToString for SQLType {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_type_with_optional_length(sql_type: &str, len: &Option<usize>) -> String {
|
||||
fn format_type_with_optional_length(sql_type: &str, len: &Option<u64>) -> String {
|
||||
let mut s = sql_type.to_string();
|
||||
if let Some(len) = len {
|
||||
s += &format!("({})", len);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/// SQL values such as int, double, string, timestamp
|
||||
/// Primitive SQL values such as number and string
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Value {
|
||||
/// Literal signed long
|
||||
Long(i64),
|
||||
/// Literal floating point value
|
||||
/// Unsigned integer value
|
||||
Long(u64),
|
||||
/// Unsigned floating point value
|
||||
Double(f64),
|
||||
/// 'string value'
|
||||
SingleQuotedString(String),
|
||||
/// N'string value'
|
||||
NationalStringLiteral(String),
|
||||
/// Boolean value true or false,
|
||||
/// Boolean value true or false
|
||||
Boolean(bool),
|
||||
/// NULL value in insert statements,
|
||||
Null,
|
||||
|
|
|
@ -351,14 +351,8 @@ impl Parser {
|
|||
let rows = if self.parse_keyword("UNBOUNDED") {
|
||||
None
|
||||
} else {
|
||||
let rows = self.parse_literal_int()?;
|
||||
if rows < 0 {
|
||||
parser_err!(format!(
|
||||
"The number of rows must be non-negative, got {}",
|
||||
rows
|
||||
))?;
|
||||
}
|
||||
Some(rows as u64)
|
||||
let rows = self.parse_literal_uint()?;
|
||||
Some(rows)
|
||||
};
|
||||
if self.parse_keyword("PRECEDING") {
|
||||
Ok(SQLWindowFrameBound::Preceding(rows))
|
||||
|
@ -1059,9 +1053,9 @@ impl Parser {
|
|||
Ok(n) => Ok(Value::Double(n)),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as f64: {}", n, e)),
|
||||
},
|
||||
Token::Number(ref n) => match n.parse::<i64>() {
|
||||
Token::Number(ref n) => match n.parse::<u64>() {
|
||||
Ok(n) => Ok(Value::Long(n)),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as u64: {}", n, e)),
|
||||
},
|
||||
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
|
||||
Token::NationalStringLiteral(ref s) => {
|
||||
|
@ -1073,13 +1067,13 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a literal integer/long
|
||||
pub fn parse_literal_int(&mut self) -> Result<i64, ParserError> {
|
||||
/// Parse an unsigned literal integer/long
|
||||
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
|
||||
match self.next_token() {
|
||||
Some(Token::Number(s)) => s.parse::<i64>().map_err(|e| {
|
||||
ParserError::ParserError(format!("Could not parse '{}' as i64: {}", s, e))
|
||||
Some(Token::Number(s)) => s.parse::<u64>().map_err(|e| {
|
||||
ParserError::ParserError(format!("Could not parse '{}' as u64: {}", s, e))
|
||||
}),
|
||||
other => parser_err!(format!("Expected literal int, found {:?}", other)),
|
||||
other => self.expected("literal int", other),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1258,17 +1252,11 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_precision(&mut self) -> Result<usize, ParserError> {
|
||||
//TODO: error handling
|
||||
Ok(self.parse_optional_precision()?.unwrap())
|
||||
}
|
||||
|
||||
pub fn parse_optional_precision(&mut self) -> Result<Option<usize>, ParserError> {
|
||||
pub fn parse_optional_precision(&mut self) -> Result<Option<u64>, ParserError> {
|
||||
if self.consume_token(&Token::LParen) {
|
||||
let n = self.parse_literal_int()?;
|
||||
//TODO: check return value of reading rparen
|
||||
let n = self.parse_literal_uint()?;
|
||||
self.expect_token(&Token::RParen)?;
|
||||
Ok(Some(n as usize))
|
||||
Ok(Some(n))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
@ -1276,16 +1264,16 @@ impl Parser {
|
|||
|
||||
pub fn parse_optional_precision_scale(
|
||||
&mut self,
|
||||
) -> Result<(Option<usize>, Option<usize>), ParserError> {
|
||||
) -> Result<(Option<u64>, Option<u64>), ParserError> {
|
||||
if self.consume_token(&Token::LParen) {
|
||||
let n = self.parse_literal_int()?;
|
||||
let n = self.parse_literal_uint()?;
|
||||
let scale = if self.consume_token(&Token::Comma) {
|
||||
Some(self.parse_literal_int()? as usize)
|
||||
Some(self.parse_literal_uint()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.expect_token(&Token::RParen)?;
|
||||
Ok((Some(n as usize), scale))
|
||||
Ok((Some(n), scale))
|
||||
} else {
|
||||
Ok((None, None))
|
||||
}
|
||||
|
@ -1725,7 +1713,7 @@ impl Parser {
|
|||
if self.parse_keyword("ALL") {
|
||||
Ok(None)
|
||||
} else {
|
||||
self.parse_literal_int()
|
||||
self.parse_literal_uint()
|
||||
.map(|n| Some(ASTNode::SQLValue(Value::Long(n))))
|
||||
}
|
||||
}
|
||||
|
@ -1733,7 +1721,7 @@ impl Parser {
|
|||
/// Parse an OFFSET clause
|
||||
pub fn parse_offset(&mut self) -> Result<ASTNode, ParserError> {
|
||||
let value = self
|
||||
.parse_literal_int()
|
||||
.parse_literal_uint()
|
||||
.map(|n| ASTNode::SQLValue(Value::Long(n)))?;
|
||||
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
|
||||
Ok(value)
|
||||
|
|
|
@ -29,7 +29,7 @@ use super::dialect::Dialect;
|
|||
pub enum Token {
|
||||
/// A keyword (like SELECT) or an optionally quoted SQL identifier
|
||||
SQLWord(SQLWord),
|
||||
/// Numeric literal
|
||||
/// An unsigned numeric literal
|
||||
Number(String),
|
||||
/// A character that could not be tokenized
|
||||
Char(char),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue