diff --git a/src/ast/query.rs b/src/ast/query.rs index efec56ffd..602e0c7e9 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -2245,6 +2245,10 @@ pub enum TableVersion { /// Databricks supports this syntax. /// For example: `SELECT * FROM tbl TIMESTAMP AS OF CURRENT_TIMESTAMP() - INTERVAL 1 HOUR` TimestampAsOf(Expr), + /// When the table version is defined using `VERSION AS OF`. + /// Databricks supports this syntax. + /// For example: `SELECT * FROM tbl VERSION AS OF 2` + VersionAsOf(Expr), /// When the table version is defined using a function. /// For example: `SELECT * FROM tbl AT(TIMESTAMP => '2020-08-14 09:30:00')` Function(Expr), @@ -2255,6 +2259,7 @@ impl Display for TableVersion { match self { TableVersion::ForSystemTimeAsOf(e) => write!(f, "FOR SYSTEM_TIME AS OF {e}")?, TableVersion::TimestampAsOf(e) => write!(f, "TIMESTAMP AS OF {e}")?, + TableVersion::VersionAsOf(e) => write!(f, "VERSION AS OF {e}")?, TableVersion::Function(func) => write!(f, "{func}")?, } Ok(()) diff --git a/src/dialect/bigquery.rs b/src/dialect/bigquery.rs index 27fd3cca3..6ad8a5089 100644 --- a/src/dialect/bigquery.rs +++ b/src/dialect/bigquery.rs @@ -136,7 +136,7 @@ impl Dialect for BigQueryDialect { } // See - fn supports_timestamp_versioning(&self) -> bool { + fn supports_table_versioning(&self) -> bool { true } diff --git a/src/dialect/databricks.rs b/src/dialect/databricks.rs index ec866295d..029709fea 100644 --- a/src/dialect/databricks.rs +++ b/src/dialect/databricks.rs @@ -48,7 +48,7 @@ impl Dialect for DatabricksDialect { } /// - fn supports_timestamp_versioning(&self) -> bool { + fn supports_table_versioning(&self) -> bool { true } diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 0b6212974..30d0e3ebc 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -1060,7 +1060,7 @@ pub trait Dialect: Debug + Any { /// Returns true if this dialect supports querying historical table data /// by specifying which version of the data to query. - fn supports_timestamp_versioning(&self) -> bool { + fn supports_table_versioning(&self) -> bool { false } diff --git a/src/dialect/mssql.rs b/src/dialect/mssql.rs index faf3402c2..eaafe9295 100644 --- a/src/dialect/mssql.rs +++ b/src/dialect/mssql.rs @@ -107,7 +107,7 @@ impl Dialect for MsSqlDialect { } /// See: - fn supports_timestamp_versioning(&self) -> bool { + fn supports_table_versioning(&self) -> bool { true } diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index ed01c128b..40ce75897 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -536,7 +536,7 @@ impl Dialect for SnowflakeDialect { } /// See: - fn supports_timestamp_versioning(&self) -> bool { + fn supports_table_versioning(&self) -> bool { true } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3294acf6a..8cc2db10c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -15484,7 +15484,7 @@ impl<'a> Parser<'a> { /// Parses a the timestamp version specifier (i.e. query historical data) pub fn maybe_parse_table_version(&mut self) -> Result, ParserError> { - if self.dialect.supports_timestamp_versioning() { + if self.dialect.supports_table_versioning() { if self.parse_keywords(&[Keyword::FOR, Keyword::SYSTEM_TIME, Keyword::AS, Keyword::OF]) { let expr = self.parse_expr()?; @@ -15496,6 +15496,9 @@ impl<'a> Parser<'a> { } else if self.parse_keywords(&[Keyword::TIMESTAMP, Keyword::AS, Keyword::OF]) { let expr = self.parse_expr()?; return Ok(Some(TableVersion::TimestampAsOf(expr))); + } else if self.parse_keywords(&[Keyword::VERSION, Keyword::AS, Keyword::OF]) { + let expr = Expr::Value(self.parse_number_value()?); + return Ok(Some(TableVersion::VersionAsOf(expr))); } } Ok(None) diff --git a/tests/sqlparser_databricks.rs b/tests/sqlparser_databricks.rs index 9a9a73fe6..91e97eb68 100644 --- a/tests/sqlparser_databricks.rs +++ b/tests/sqlparser_databricks.rs @@ -369,14 +369,21 @@ fn data_type_timestamp_ntz() { #[test] fn parse_table_time_travel() { - all_dialects_where(|d| d.supports_timestamp_versioning()) + all_dialects_where(|d| d.supports_table_versioning()) .verified_only_select("SELECT 1 FROM t1 TIMESTAMP AS OF '2018-10-18T22:15:12.013Z'"); - all_dialects_where(|d| d.supports_timestamp_versioning()).verified_only_select( + all_dialects_where(|d| d.supports_table_versioning()).verified_only_select( "SELECT 1 FROM t1 TIMESTAMP AS OF CURRENT_TIMESTAMP() - INTERVAL 12 HOURS", ); + all_dialects_where(|d| d.supports_table_versioning()) + .verified_only_select("SELECT 1 FROM t1 VERSION AS OF 1"); + assert!(databricks() .parse_sql_statements("SELECT 1 FROM t1 FOR TIMESTAMP AS OF 'some_timestamp'") .is_err()); + + assert!(all_dialects_where(|d| d.supports_table_versioning()) + .parse_sql_statements("SELECT 1 FROM t1 VERSION AS OF 1 - 2",) + .is_err()) }