mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 14:28:22 +00:00
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.
This commit is contained in:
parent
9297ffbe18
commit
de177f107c
4 changed files with 21 additions and 147 deletions
|
@ -20,7 +20,6 @@ path = "src/lib.rs"
|
|||
|
||||
[dependencies]
|
||||
log = "0.4.5"
|
||||
chrono = "0.4.6"
|
||||
|
||||
[dev-dependencies]
|
||||
simple_logger = "1.0.1"
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use chrono::{offset::FixedOffset, DateTime, NaiveDate, NaiveDateTime, NaiveTime};
|
||||
|
||||
/// SQL values such as int, double, string, timestamp
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Value {
|
||||
|
@ -13,14 +11,6 @@ pub enum Value {
|
|||
NationalStringLiteral(String),
|
||||
/// Boolean value true or false,
|
||||
Boolean(bool),
|
||||
/// Date value
|
||||
Date(NaiveDate),
|
||||
// Time
|
||||
Time(NaiveTime),
|
||||
/// Date and time
|
||||
DateTime(NaiveDateTime),
|
||||
/// Timstamp with time zone
|
||||
Timestamp(DateTime<FixedOffset>),
|
||||
/// NULL value in insert statements,
|
||||
Null,
|
||||
}
|
||||
|
@ -33,10 +23,6 @@ impl ToString for Value {
|
|||
Value::SingleQuotedString(v) => format!("'{}'", escape_single_quote_string(v)),
|
||||
Value::NationalStringLiteral(v) => format!("N'{}'", v),
|
||||
Value::Boolean(v) => v.to_string(),
|
||||
Value::Date(v) => v.to_string(),
|
||||
Value::Time(v) => v.to_string(),
|
||||
Value::DateTime(v) => v.to_string(),
|
||||
Value::Timestamp(v) => format!("{}", v),
|
||||
Value::Null => "NULL".to_string(),
|
||||
}
|
||||
}
|
||||
|
|
131
src/sqlparser.rs
131
src/sqlparser.rs
|
@ -20,7 +20,6 @@ use super::dialect::keywords;
|
|||
use super::dialect::Dialect;
|
||||
use super::sqlast::*;
|
||||
use super::sqltokenizer::*;
|
||||
use chrono::{offset::FixedOffset, DateTime, NaiveDate, NaiveDateTime, NaiveTime};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ParserError {
|
||||
|
@ -922,37 +921,29 @@ impl Parser {
|
|||
/// Parse a literal value (numbers, strings, date/time, booleans)
|
||||
fn parse_value(&mut self) -> Result<Value, ParserError> {
|
||||
match self.next_token() {
|
||||
Some(t) => {
|
||||
match t {
|
||||
Token::SQLWord(k) => match k.keyword.as_ref() {
|
||||
"TRUE" => Ok(Value::Boolean(true)),
|
||||
"FALSE" => Ok(Value::Boolean(false)),
|
||||
"NULL" => Ok(Value::Null),
|
||||
_ => {
|
||||
return parser_err!(format!(
|
||||
"No value parser for keyword {}",
|
||||
k.keyword
|
||||
));
|
||||
}
|
||||
},
|
||||
//TODO: parse the timestamp here (see parse_timestamp_value())
|
||||
Token::Number(ref n) if n.contains('.') => match n.parse::<f64>() {
|
||||
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>() {
|
||||
Ok(n) => Ok(Value::Long(n)),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
|
||||
},
|
||||
Token::SingleQuotedString(ref s) => {
|
||||
Ok(Value::SingleQuotedString(s.to_string()))
|
||||
Some(t) => match t {
|
||||
Token::SQLWord(k) => match k.keyword.as_ref() {
|
||||
"TRUE" => Ok(Value::Boolean(true)),
|
||||
"FALSE" => Ok(Value::Boolean(false)),
|
||||
"NULL" => Ok(Value::Null),
|
||||
_ => {
|
||||
return parser_err!(format!("No value parser for keyword {}", k.keyword));
|
||||
}
|
||||
Token::NationalStringLiteral(ref s) => {
|
||||
Ok(Value::NationalStringLiteral(s.to_string()))
|
||||
}
|
||||
_ => parser_err!(format!("Unsupported value: {:?}", t)),
|
||||
},
|
||||
Token::Number(ref n) if n.contains('.') => match n.parse::<f64>() {
|
||||
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>() {
|
||||
Ok(n) => Ok(Value::Long(n)),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
|
||||
},
|
||||
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
|
||||
Token::NationalStringLiteral(ref s) => {
|
||||
Ok(Value::NationalStringLiteral(s.to_string()))
|
||||
}
|
||||
}
|
||||
_ => parser_err!(format!("Unsupported value: {:?}", t)),
|
||||
},
|
||||
None => parser_err!("Expecting a value, but found EOF"),
|
||||
}
|
||||
}
|
||||
|
@ -985,86 +976,6 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_timezone_offset(&mut self) -> Result<i8, ParserError> {
|
||||
match self.next_token() {
|
||||
Some(Token::Plus) => {
|
||||
let n = self.parse_literal_int()?;
|
||||
Ok(n as i8)
|
||||
}
|
||||
Some(Token::Minus) => {
|
||||
let n = self.parse_literal_int()?;
|
||||
Ok(-n as i8)
|
||||
}
|
||||
other => parser_err!(format!(
|
||||
"Expecting `+` or `-` in timezone, but found {:?}",
|
||||
other
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_timestamp_value(&mut self) -> Result<Value, ParserError> {
|
||||
let year = self.parse_literal_int()?;
|
||||
let date = self.parse_date(year)?;
|
||||
if let Ok(time) = self.parse_time() {
|
||||
let date_time = NaiveDateTime::new(date, time);
|
||||
match self.peek_token() {
|
||||
Some(token) => match token {
|
||||
Token::Plus | Token::Minus => {
|
||||
let tz = self.parse_timezone_offset()?;
|
||||
let offset = FixedOffset::east(i32::from(tz) * 3600);
|
||||
Ok(Value::Timestamp(DateTime::from_utc(date_time, offset)))
|
||||
}
|
||||
_ => Ok(Value::DateTime(date_time)),
|
||||
},
|
||||
_ => Ok(Value::DateTime(date_time)),
|
||||
}
|
||||
} else {
|
||||
parser_err!(format!(
|
||||
"Expecting time after date, but found {:?}",
|
||||
self.peek_token()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_date(&mut self, year: i64) -> Result<NaiveDate, ParserError> {
|
||||
if self.consume_token(&Token::Minus) {
|
||||
let month = self.parse_literal_int()?;
|
||||
if self.consume_token(&Token::Minus) {
|
||||
let day = self.parse_literal_int()?;
|
||||
let date = NaiveDate::from_ymd(year as i32, month as u32, day as u32);
|
||||
Ok(date)
|
||||
} else {
|
||||
parser_err!(format!(
|
||||
"Expecting `-` for date separator, found {:?}",
|
||||
self.peek_token()
|
||||
))
|
||||
}
|
||||
} else {
|
||||
parser_err!(format!(
|
||||
"Expecting `-` for date separator, found {:?}",
|
||||
self.peek_token()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_time(&mut self) -> Result<NaiveTime, ParserError> {
|
||||
let hour = self.parse_literal_int()?;
|
||||
self.expect_token(&Token::Colon)?;
|
||||
let min = self.parse_literal_int()?;
|
||||
self.expect_token(&Token::Colon)?;
|
||||
// On one hand, the SQL specs defines <seconds fraction> ::= <unsigned integer>,
|
||||
// so it would be more correct to parse it as such
|
||||
let sec = self.parse_literal_double()?;
|
||||
// On the other, chrono only supports nanoseconds, which should(?) fit in seconds-as-f64...
|
||||
let nanos = (sec.fract() * 1_000_000_000.0).round();
|
||||
Ok(NaiveTime::from_hms_nano(
|
||||
hour as u32,
|
||||
min as u32,
|
||||
sec as u32,
|
||||
nanos as u32,
|
||||
))
|
||||
}
|
||||
|
||||
/// Parse a SQL datatype (in the context of a CREATE TABLE statement for example)
|
||||
pub fn parse_data_type(&mut self) -> Result<SQLType, ParserError> {
|
||||
match self.next_token() {
|
||||
|
|
|
@ -209,22 +209,6 @@ PHP ₱ USD $
|
|||
//assert_eq!(sql, ast.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_timestamps_example() {
|
||||
let sql = "2016-02-15 09:43:33";
|
||||
let _ = parse_sql_expr(sql);
|
||||
//TODO add assertion
|
||||
//assert_eq!(sql, ast.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_timestamps_with_millis_example() {
|
||||
let sql = "2017-11-02 19:15:42.308637";
|
||||
let _ = parse_sql_expr(sql);
|
||||
//TODO add assertion
|
||||
//assert_eq!(sql, ast.to_string());
|
||||
}
|
||||
|
||||
fn verified_stmt(query: &str) -> SQLStatement {
|
||||
one_statement_parses_to(query, query)
|
||||
}
|
||||
|
@ -247,12 +231,6 @@ fn parse_sql_statements(sql: &str) -> Result<Vec<SQLStatement>, ParserError> {
|
|||
Parser::parse_sql(&PostgreSqlDialect {}, sql.to_string())
|
||||
}
|
||||
|
||||
fn parse_sql_expr(sql: &str) -> ASTNode {
|
||||
debug!("sql: {}", sql);
|
||||
let mut parser = parser(sql);
|
||||
parser.parse_expr().unwrap()
|
||||
}
|
||||
|
||||
fn parser(sql: &str) -> Parser {
|
||||
let dialect = PostgreSqlDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, &sql);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue