Skip to content

Commit 1492f42

Browse files
committed
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.
1 parent bc537fa commit 1492f42

File tree

4 files changed

+33
-45
lines changed

4 files changed

+33
-45
lines changed

src/sqlast/sqltype.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
use super::SQLObjectName;
22

3-
/// SQL datatypes for literals in SQL statements
3+
/// SQL data types
44
#[derive(Debug, Clone, PartialEq)]
55
pub enum SQLType {
66
/// Fixed-length character type e.g. CHAR(10)
7-
Char(Option<usize>),
7+
Char(Option<u64>),
88
/// Variable-length character type e.g. VARCHAR(10)
9-
Varchar(Option<usize>),
9+
Varchar(Option<u64>),
1010
/// Uuid type
1111
Uuid,
1212
/// Large character object e.g. CLOB(1000)
13-
Clob(usize),
13+
Clob(u64),
1414
/// Fixed-length binary type e.g. BINARY(10)
15-
Binary(usize),
15+
Binary(u64),
1616
/// Variable-length binary type e.g. VARBINARY(10)
17-
Varbinary(usize),
17+
Varbinary(u64),
1818
/// Large binary object e.g. BLOB(1000)
19-
Blob(usize),
19+
Blob(u64),
2020
/// Decimal type with optional precision and scale e.g. DECIMAL(10,2)
21-
Decimal(Option<usize>, Option<usize>),
21+
Decimal(Option<u64>, Option<u64>),
2222
/// Floating point with optional precision e.g. FLOAT(8)
23-
Float(Option<usize>),
23+
Float(Option<u64>),
2424
/// Small integer
2525
SmallInt,
2626
/// Integer
@@ -87,7 +87,7 @@ impl ToString for SQLType {
8787
}
8888
}
8989

90-
fn format_type_with_optional_length(sql_type: &str, len: &Option<usize>) -> String {
90+
fn format_type_with_optional_length(sql_type: &str, len: &Option<u64>) -> String {
9191
let mut s = sql_type.to_string();
9292
if let Some(len) = len {
9393
s += &format!("({})", len);

src/sqlast/value.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
/// SQL values such as int, double, string, timestamp
1+
/// Primitive SQL values such as number and string
22
#[derive(Debug, Clone, PartialEq)]
33
pub enum Value {
4-
/// Literal signed long
5-
Long(i64),
6-
/// Literal floating point value
4+
/// Unsigned integer value
5+
Long(u64),
6+
/// Unsigned floating point value
77
Double(f64),
88
/// 'string value'
99
SingleQuotedString(String),
1010
/// N'string value'
1111
NationalStringLiteral(String),
12-
/// Boolean value true or false,
12+
/// Boolean value true or false
1313
Boolean(bool),
1414
/// NULL value in insert statements,
1515
Null,

src/sqlparser.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,8 @@ impl Parser {
322322
let rows = if self.parse_keyword("UNBOUNDED") {
323323
None
324324
} else {
325-
let rows = self.parse_literal_int()?;
326-
if rows < 0 {
327-
parser_err!(format!(
328-
"The number of rows must be non-negative, got {}",
329-
rows
330-
))?;
331-
}
332-
Some(rows as u64)
325+
let rows = self.parse_literal_uint()?;
326+
Some(rows)
333327
};
334328
if self.parse_keyword("PRECEDING") {
335329
Ok(SQLWindowFrameBound::Preceding(rows))
@@ -968,9 +962,9 @@ impl Parser {
968962
Ok(n) => Ok(Value::Double(n)),
969963
Err(e) => parser_err!(format!("Could not parse '{}' as f64: {}", n, e)),
970964
},
971-
Token::Number(ref n) => match n.parse::<i64>() {
965+
Token::Number(ref n) => match n.parse::<u64>() {
972966
Ok(n) => Ok(Value::Long(n)),
973-
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
967+
Err(e) => parser_err!(format!("Could not parse '{}' as u64: {}", n, e)),
974968
},
975969
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
976970
Token::NationalStringLiteral(ref s) => {
@@ -982,13 +976,13 @@ impl Parser {
982976
}
983977
}
984978

985-
/// Parse a literal integer/long
986-
pub fn parse_literal_int(&mut self) -> Result<i64, ParserError> {
979+
/// Parse an unsigned literal integer/long
980+
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
987981
match self.next_token() {
988-
Some(Token::Number(s)) => s.parse::<i64>().map_err(|e| {
989-
ParserError::ParserError(format!("Could not parse '{}' as i64: {}", s, e))
982+
Some(Token::Number(s)) => s.parse::<u64>().map_err(|e| {
983+
ParserError::ParserError(format!("Could not parse '{}' as u64: {}", s, e))
990984
}),
991-
other => parser_err!(format!("Expected literal int, found {:?}", other)),
985+
other => self.expected("literal int", other),
992986
}
993987
}
994988

@@ -1167,34 +1161,28 @@ impl Parser {
11671161
}
11681162
}
11691163

1170-
pub fn parse_precision(&mut self) -> Result<usize, ParserError> {
1171-
//TODO: error handling
1172-
Ok(self.parse_optional_precision()?.unwrap())
1173-
}
1174-
1175-
pub fn parse_optional_precision(&mut self) -> Result<Option<usize>, ParserError> {
1164+
pub fn parse_optional_precision(&mut self) -> Result<Option<u64>, ParserError> {
11761165
if self.consume_token(&Token::LParen) {
1177-
let n = self.parse_literal_int()?;
1178-
//TODO: check return value of reading rparen
1166+
let n = self.parse_literal_uint()?;
11791167
self.expect_token(&Token::RParen)?;
1180-
Ok(Some(n as usize))
1168+
Ok(Some(n))
11811169
} else {
11821170
Ok(None)
11831171
}
11841172
}
11851173

11861174
pub fn parse_optional_precision_scale(
11871175
&mut self,
1188-
) -> Result<(Option<usize>, Option<usize>), ParserError> {
1176+
) -> Result<(Option<u64>, Option<u64>), ParserError> {
11891177
if self.consume_token(&Token::LParen) {
1190-
let n = self.parse_literal_int()?;
1178+
let n = self.parse_literal_uint()?;
11911179
let scale = if self.consume_token(&Token::Comma) {
1192-
Some(self.parse_literal_int()? as usize)
1180+
Some(self.parse_literal_uint()?)
11931181
} else {
11941182
None
11951183
};
11961184
self.expect_token(&Token::RParen)?;
1197-
Ok((Some(n as usize), scale))
1185+
Ok((Some(n), scale))
11981186
} else {
11991187
Ok((None, None))
12001188
}
@@ -1609,7 +1597,7 @@ impl Parser {
16091597
if self.parse_keyword("ALL") {
16101598
Ok(None)
16111599
} else {
1612-
self.parse_literal_int()
1600+
self.parse_literal_uint()
16131601
.map(|n| Some(ASTNode::SQLValue(Value::Long(n))))
16141602
}
16151603
}

src/sqltokenizer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use super::dialect::Dialect;
2929
pub enum Token {
3030
/// A keyword (like SELECT) or an optionally quoted SQL identifier
3131
SQLWord(SQLWord),
32-
/// Numeric literal
32+
/// An unsigned numeric literal
3333
Number(String),
3434
/// A character that could not be tokenized
3535
Char(char),

0 commit comments

Comments
 (0)