Skip to content

Commit de177f1

Browse files
committed
Remove dead datetime-related code
1) Removed unused date/time parsing methods from `Parser` I don't see how the token-based parsing code would ever be used: the date/time literals are usually quoted, like `DATE 'yyyy-mm-dd'` or simply `'YYYYMMDD'`, so the date will be a single token. 2) Removed unused date/time related variants from `Value` and the dependency on `chrono`. We don't support parsing date/time literals at the moment and when we do I think we should store the exact String to let the consumer parse it as they see fit. 3) Removed `parse_timestamps_example` and `parse_timestamps_with_millis_example` tests. They parsed as `number(2016) minus number(02) minus number(15) <END OF EXPRESSION>` (leaving the time part unparsed) as it makes no sense to try parsing a yyyy-mm-dd value as an SQL expression.
1 parent 9297ffb commit de177f1

File tree

4 files changed

+21
-147
lines changed

4 files changed

+21
-147
lines changed

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ path = "src/lib.rs"
2020

2121
[dependencies]
2222
log = "0.4.5"
23-
chrono = "0.4.6"
2423

2524
[dev-dependencies]
2625
simple_logger = "1.0.1"

src/sqlast/value.rs

-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use chrono::{offset::FixedOffset, DateTime, NaiveDate, NaiveDateTime, NaiveTime};
2-
31
/// SQL values such as int, double, string, timestamp
42
#[derive(Debug, Clone, PartialEq)]
53
pub enum Value {
@@ -13,14 +11,6 @@ pub enum Value {
1311
NationalStringLiteral(String),
1412
/// Boolean value true or false,
1513
Boolean(bool),
16-
/// Date value
17-
Date(NaiveDate),
18-
// Time
19-
Time(NaiveTime),
20-
/// Date and time
21-
DateTime(NaiveDateTime),
22-
/// Timstamp with time zone
23-
Timestamp(DateTime<FixedOffset>),
2414
/// NULL value in insert statements,
2515
Null,
2616
}
@@ -33,10 +23,6 @@ impl ToString for Value {
3323
Value::SingleQuotedString(v) => format!("'{}'", escape_single_quote_string(v)),
3424
Value::NationalStringLiteral(v) => format!("N'{}'", v),
3525
Value::Boolean(v) => v.to_string(),
36-
Value::Date(v) => v.to_string(),
37-
Value::Time(v) => v.to_string(),
38-
Value::DateTime(v) => v.to_string(),
39-
Value::Timestamp(v) => format!("{}", v),
4026
Value::Null => "NULL".to_string(),
4127
}
4228
}

src/sqlparser.rs

+21-110
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use super::dialect::keywords;
2020
use super::dialect::Dialect;
2121
use super::sqlast::*;
2222
use super::sqltokenizer::*;
23-
use chrono::{offset::FixedOffset, DateTime, NaiveDate, NaiveDateTime, NaiveTime};
2423

2524
#[derive(Debug, Clone, PartialEq)]
2625
pub enum ParserError {
@@ -922,37 +921,29 @@ impl Parser {
922921
/// Parse a literal value (numbers, strings, date/time, booleans)
923922
fn parse_value(&mut self) -> Result<Value, ParserError> {
924923
match self.next_token() {
925-
Some(t) => {
926-
match t {
927-
Token::SQLWord(k) => match k.keyword.as_ref() {
928-
"TRUE" => Ok(Value::Boolean(true)),
929-
"FALSE" => Ok(Value::Boolean(false)),
930-
"NULL" => Ok(Value::Null),
931-
_ => {
932-
return parser_err!(format!(
933-
"No value parser for keyword {}",
934-
k.keyword
935-
));
936-
}
937-
},
938-
//TODO: parse the timestamp here (see parse_timestamp_value())
939-
Token::Number(ref n) if n.contains('.') => match n.parse::<f64>() {
940-
Ok(n) => Ok(Value::Double(n)),
941-
Err(e) => parser_err!(format!("Could not parse '{}' as f64: {}", n, e)),
942-
},
943-
Token::Number(ref n) => match n.parse::<i64>() {
944-
Ok(n) => Ok(Value::Long(n)),
945-
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
946-
},
947-
Token::SingleQuotedString(ref s) => {
948-
Ok(Value::SingleQuotedString(s.to_string()))
949-
}
950-
Token::NationalStringLiteral(ref s) => {
951-
Ok(Value::NationalStringLiteral(s.to_string()))
924+
Some(t) => match t {
925+
Token::SQLWord(k) => match k.keyword.as_ref() {
926+
"TRUE" => Ok(Value::Boolean(true)),
927+
"FALSE" => Ok(Value::Boolean(false)),
928+
"NULL" => Ok(Value::Null),
929+
_ => {
930+
return parser_err!(format!("No value parser for keyword {}", k.keyword));
952931
}
953-
_ => parser_err!(format!("Unsupported value: {:?}", t)),
932+
},
933+
Token::Number(ref n) if n.contains('.') => match n.parse::<f64>() {
934+
Ok(n) => Ok(Value::Double(n)),
935+
Err(e) => parser_err!(format!("Could not parse '{}' as f64: {}", n, e)),
936+
},
937+
Token::Number(ref n) => match n.parse::<i64>() {
938+
Ok(n) => Ok(Value::Long(n)),
939+
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
940+
},
941+
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
942+
Token::NationalStringLiteral(ref s) => {
943+
Ok(Value::NationalStringLiteral(s.to_string()))
954944
}
955-
}
945+
_ => parser_err!(format!("Unsupported value: {:?}", t)),
946+
},
956947
None => parser_err!("Expecting a value, but found EOF"),
957948
}
958949
}
@@ -985,86 +976,6 @@ impl Parser {
985976
}
986977
}
987978

988-
pub fn parse_timezone_offset(&mut self) -> Result<i8, ParserError> {
989-
match self.next_token() {
990-
Some(Token::Plus) => {
991-
let n = self.parse_literal_int()?;
992-
Ok(n as i8)
993-
}
994-
Some(Token::Minus) => {
995-
let n = self.parse_literal_int()?;
996-
Ok(-n as i8)
997-
}
998-
other => parser_err!(format!(
999-
"Expecting `+` or `-` in timezone, but found {:?}",
1000-
other
1001-
)),
1002-
}
1003-
}
1004-
1005-
pub fn parse_timestamp_value(&mut self) -> Result<Value, ParserError> {
1006-
let year = self.parse_literal_int()?;
1007-
let date = self.parse_date(year)?;
1008-
if let Ok(time) = self.parse_time() {
1009-
let date_time = NaiveDateTime::new(date, time);
1010-
match self.peek_token() {
1011-
Some(token) => match token {
1012-
Token::Plus | Token::Minus => {
1013-
let tz = self.parse_timezone_offset()?;
1014-
let offset = FixedOffset::east(i32::from(tz) * 3600);
1015-
Ok(Value::Timestamp(DateTime::from_utc(date_time, offset)))
1016-
}
1017-
_ => Ok(Value::DateTime(date_time)),
1018-
},
1019-
_ => Ok(Value::DateTime(date_time)),
1020-
}
1021-
} else {
1022-
parser_err!(format!(
1023-
"Expecting time after date, but found {:?}",
1024-
self.peek_token()
1025-
))
1026-
}
1027-
}
1028-
1029-
pub fn parse_date(&mut self, year: i64) -> Result<NaiveDate, ParserError> {
1030-
if self.consume_token(&Token::Minus) {
1031-
let month = self.parse_literal_int()?;
1032-
if self.consume_token(&Token::Minus) {
1033-
let day = self.parse_literal_int()?;
1034-
let date = NaiveDate::from_ymd(year as i32, month as u32, day as u32);
1035-
Ok(date)
1036-
} else {
1037-
parser_err!(format!(
1038-
"Expecting `-` for date separator, found {:?}",
1039-
self.peek_token()
1040-
))
1041-
}
1042-
} else {
1043-
parser_err!(format!(
1044-
"Expecting `-` for date separator, found {:?}",
1045-
self.peek_token()
1046-
))
1047-
}
1048-
}
1049-
1050-
pub fn parse_time(&mut self) -> Result<NaiveTime, ParserError> {
1051-
let hour = self.parse_literal_int()?;
1052-
self.expect_token(&Token::Colon)?;
1053-
let min = self.parse_literal_int()?;
1054-
self.expect_token(&Token::Colon)?;
1055-
// On one hand, the SQL specs defines <seconds fraction> ::= <unsigned integer>,
1056-
// so it would be more correct to parse it as such
1057-
let sec = self.parse_literal_double()?;
1058-
// On the other, chrono only supports nanoseconds, which should(?) fit in seconds-as-f64...
1059-
let nanos = (sec.fract() * 1_000_000_000.0).round();
1060-
Ok(NaiveTime::from_hms_nano(
1061-
hour as u32,
1062-
min as u32,
1063-
sec as u32,
1064-
nanos as u32,
1065-
))
1066-
}
1067-
1068979
/// Parse a SQL datatype (in the context of a CREATE TABLE statement for example)
1069980
pub fn parse_data_type(&mut self) -> Result<SQLType, ParserError> {
1070981
match self.next_token() {

tests/sqlparser_postgres.rs

-22
Original file line numberDiff line numberDiff line change
@@ -209,22 +209,6 @@ PHP ₱ USD $
209209
//assert_eq!(sql, ast.to_string());
210210
}
211211

212-
#[test]
213-
fn parse_timestamps_example() {
214-
let sql = "2016-02-15 09:43:33";
215-
let _ = parse_sql_expr(sql);
216-
//TODO add assertion
217-
//assert_eq!(sql, ast.to_string());
218-
}
219-
220-
#[test]
221-
fn parse_timestamps_with_millis_example() {
222-
let sql = "2017-11-02 19:15:42.308637";
223-
let _ = parse_sql_expr(sql);
224-
//TODO add assertion
225-
//assert_eq!(sql, ast.to_string());
226-
}
227-
228212
fn verified_stmt(query: &str) -> SQLStatement {
229213
one_statement_parses_to(query, query)
230214
}
@@ -247,12 +231,6 @@ fn parse_sql_statements(sql: &str) -> Result<Vec<SQLStatement>, ParserError> {
247231
Parser::parse_sql(&PostgreSqlDialect {}, sql.to_string())
248232
}
249233

250-
fn parse_sql_expr(sql: &str) -> ASTNode {
251-
debug!("sql: {}", sql);
252-
let mut parser = parser(sql);
253-
parser.parse_expr().unwrap()
254-
}
255-
256234
fn parser(sql: &str) -> Parser {
257235
let dialect = PostgreSqlDialect {};
258236
let mut tokenizer = Tokenizer::new(&dialect, &sql);

0 commit comments

Comments
 (0)