diff --git a/src/sqlast/value.rs b/src/sqlast/value.rs index fc9df0d8e..21bb199d4 100644 --- a/src/sqlast/value.rs +++ b/src/sqlast/value.rs @@ -15,6 +15,12 @@ pub enum Value { HexStringLiteral(String), /// Boolean value true or false Boolean(bool), + /// Date literals + Date(String), + /// Time literals + Time(String), + /// Timestamp literals, which include both a date and time + Timestamp(String), /// NULL value in insert statements, Null, } @@ -28,6 +34,9 @@ impl ToString for Value { Value::NationalStringLiteral(v) => format!("N'{}'", v), Value::HexStringLiteral(v) => format!("X'{}'", v), Value::Boolean(v) => v.to_string(), + Value::Date(v) => format!("DATE '{}'", escape_single_quote_string(v)), + Value::Time(v) => format!("TIME '{}'", escape_single_quote_string(v)), + Value::Timestamp(v) => format!("TIMESTAMP '{}'", escape_single_quote_string(v)), Value::Null => "NULL".to_string(), } } diff --git a/src/sqlparser.rs b/src/sqlparser.rs index 35c751067..1b1b83b61 100644 --- a/src/sqlparser.rs +++ b/src/sqlparser.rs @@ -192,12 +192,17 @@ impl Parser { } "CASE" => self.parse_case_expression(), "CAST" => self.parse_cast_expression(), + "DATE" => Ok(ASTNode::SQLValue(Value::Date(self.parse_literal_string()?))), "EXISTS" => self.parse_exists_expression(), "EXTRACT" => self.parse_extract_expression(), "NOT" => Ok(ASTNode::SQLUnary { operator: SQLOperator::Not, expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?), }), + "TIME" => Ok(ASTNode::SQLValue(Value::Time(self.parse_literal_string()?))), + "TIMESTAMP" => Ok(ASTNode::SQLValue(Value::Timestamp( + self.parse_literal_string()?, + ))), // Here `w` is a word, check if it's a part of a multi-part // identifier, a function call, or a simple identifier: _ => match self.peek_token() { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index df50ecb7e..1c051ca00 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -1085,6 +1085,36 @@ fn parse_literal_string() { one_statement_parses_to("SELECT x'deadBEEF'", "SELECT X'deadBEEF'"); } +#[test] +fn parse_literal_date() { + let sql = "SELECT DATE '1999-01-01'"; + let select = verified_only_select(sql); + assert_eq!( + &ASTNode::SQLValue(Value::Date("1999-01-01".into())), + expr_from_projection(only(&select.projection)), + ); +} + +#[test] +fn parse_literal_time() { + let sql = "SELECT TIME '01:23:34'"; + let select = verified_only_select(sql); + assert_eq!( + &ASTNode::SQLValue(Value::Time("01:23:34".into())), + expr_from_projection(only(&select.projection)), + ); +} + +#[test] +fn parse_literal_timestamp() { + let sql = "SELECT TIMESTAMP '1999-01-01 01:23:34'"; + let select = verified_only_select(sql); + assert_eq!( + &ASTNode::SQLValue(Value::Timestamp("1999-01-01 01:23:34".into())), + expr_from_projection(only(&select.projection)), + ); +} + #[test] fn parse_simple_math_expr_plus() { let sql = "SELECT a + b, 2 + a, 2.5 + a, a_f + b_f, 2 + a_f, 2.5 + a_f FROM c";