diff --git a/src/ast/data_type.rs b/src/ast/data_type.rs index da9ff1ad1..3a6ebf4cd 100644 --- a/src/ast/data_type.rs +++ b/src/ast/data_type.rs @@ -77,8 +77,10 @@ pub enum DataType { Time, /// Datetime Datetime, - /// Timestamp + /// Timestamp [Without Time Zone] Timestamp, + /// Timestamp With Time Zone + TimestampTz, /// Interval Interval, /// Regclass used in postgresql serial @@ -157,6 +159,7 @@ impl fmt::Display for DataType { DataType::Time => write!(f, "TIME"), DataType::Datetime => write!(f, "DATETIME"), DataType::Timestamp => write!(f, "TIMESTAMP"), + DataType::TimestampTz => write!(f, "TIMESTAMPTZ"), DataType::Interval => write!(f, "INTERVAL"), DataType::Regclass => write!(f, "REGCLASS"), DataType::Text => write!(f, "TEXT"), diff --git a/src/keywords.rs b/src/keywords.rs index a06ddc48d..3a7157204 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -505,6 +505,7 @@ define_keywords!( TIES, TIME, TIMESTAMP, + TIMESTAMPTZ, TIMEZONE, TIMEZONE_HOUR, TIMEZONE_MINUTE, diff --git a/src/parser.rs b/src/parser.rs index 4cfbdd23b..e9aeeda5a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3119,12 +3119,17 @@ impl<'a> Parser<'a> { Keyword::DATE => Ok(DataType::Date), Keyword::DATETIME => Ok(DataType::Datetime), Keyword::TIMESTAMP => { - // TBD: we throw away "with/without timezone" information - if self.parse_keyword(Keyword::WITH) || self.parse_keyword(Keyword::WITHOUT) { + if self.parse_keyword(Keyword::WITH) { self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?; + Ok(DataType::TimestampTz) + } else if self.parse_keyword(Keyword::WITHOUT) { + self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?; + Ok(DataType::Timestamp) + } else { + Ok(DataType::Timestamp) } - Ok(DataType::Timestamp) } + Keyword::TIMESTAMPTZ => Ok(DataType::TimestampTz), Keyword::TIME => { // TBD: we throw away "with/without timezone" information if self.parse_keyword(Keyword::WITH) || self.parse_keyword(Keyword::WITHOUT) { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 65d699b3f..53ec83106 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2854,7 +2854,7 @@ fn parse_literal_datetime() { } #[test] -fn parse_literal_timestamp() { +fn parse_literal_timestamp_without_time_zone() { let sql = "SELECT TIMESTAMP '1999-01-01 01:23:34'"; let select = verified_only_select(sql); assert_eq!( @@ -2864,6 +2864,29 @@ fn parse_literal_timestamp() { }, expr_from_projection(only(&select.projection)), ); + + one_statement_parses_to( + "SELECT TIMESTAMP WITHOUT TIME ZONE '1999-01-01 01:23:34'", + sql, + ); +} + +#[test] +fn parse_literal_timestamp_with_time_zone() { + let sql = "SELECT TIMESTAMPTZ '1999-01-01 01:23:34Z'"; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::TimestampTz, + value: "1999-01-01 01:23:34Z".into() + }, + expr_from_projection(only(&select.projection)), + ); + + one_statement_parses_to( + "SELECT TIMESTAMP WITH TIME ZONE '1999-01-01 01:23:34Z'", + sql, + ); } #[test]