This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new ce74e7fe Databricks: Support Timetravel With "TIMESTAMP AS OF" (#2134)
ce74e7fe is described below
commit ce74e7fe217ac5d2cb5392237a03c7d252a3ea6a
Author: James Vorderbruggen <[email protected]>
AuthorDate: Wed Jan 7 05:33:10 2026 -0600
Databricks: Support Timetravel With "TIMESTAMP AS OF" (#2134)
Co-authored-by: Ifeanyi Ubah <[email protected]>
---
src/ast/query.rs | 5 +++++
src/dialect/databricks.rs | 5 +++++
src/parser/mod.rs | 3 +++
tests/sqlparser_bigquery.rs | 2 +-
tests/sqlparser_databricks.rs | 14 ++++++++++++++
5 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/ast/query.rs b/src/ast/query.rs
index 16fc9ec0..efec56ff 100644
--- a/src/ast/query.rs
+++ b/src/ast/query.rs
@@ -2241,6 +2241,10 @@ pub enum TableVersion {
/// When the table version is defined using `FOR SYSTEM_TIME AS OF`.
/// For example: `SELECT * FROM tbl FOR SYSTEM_TIME AS OF
TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)`
ForSystemTimeAsOf(Expr),
+ /// When the table version is defined using `TIMESTAMP AS OF`.
+ /// 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 a function.
/// For example: `SELECT * FROM tbl AT(TIMESTAMP => '2020-08-14 09:30:00')`
Function(Expr),
@@ -2250,6 +2254,7 @@ impl Display for TableVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TableVersion::ForSystemTimeAsOf(e) => write!(f, "FOR SYSTEM_TIME
AS OF {e}")?,
+ TableVersion::TimestampAsOf(e) => write!(f, "TIMESTAMP AS OF
{e}")?,
TableVersion::Function(func) => write!(f, "{func}")?,
}
Ok(())
diff --git a/src/dialect/databricks.rs b/src/dialect/databricks.rs
index c5d5f974..ec866295 100644
--- a/src/dialect/databricks.rs
+++ b/src/dialect/databricks.rs
@@ -47,6 +47,11 @@ impl Dialect for DatabricksDialect {
true
}
+ ///
<https://docs.databricks.com/gcp/en/delta/history#delta-time-travel-syntax>
+ fn supports_timestamp_versioning(&self) -> bool {
+ true
+ }
+
fn supports_lambda_functions(&self) -> bool {
true
}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 373076f1..4e914df7 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -15493,6 +15493,9 @@ impl<'a> Parser<'a> {
let func_name = self.parse_object_name(true)?;
let func = self.parse_function(func_name)?;
return Ok(Some(TableVersion::Function(func)));
+ } else if self.parse_keywords(&[Keyword::TIMESTAMP, Keyword::AS,
Keyword::OF]) {
+ let expr = self.parse_expr()?;
+ return Ok(Some(TableVersion::TimestampAsOf(expr)));
}
}
Ok(None)
diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs
index 2bdeba91..d8c3ada1 100644
--- a/tests/sqlparser_bigquery.rs
+++ b/tests/sqlparser_bigquery.rs
@@ -1739,7 +1739,7 @@ fn parse_table_time_travel() {
args: None,
with_hints: vec![],
version: Some(TableVersion::ForSystemTimeAsOf(Expr::Value(
- Value::SingleQuotedString(version).with_empty_span()
+
Value::SingleQuotedString(version.clone()).with_empty_span()
))),
partitions: vec![],
with_ordinality: false,
diff --git a/tests/sqlparser_databricks.rs b/tests/sqlparser_databricks.rs
index 065e8f9e..9a9a73fe 100644
--- a/tests/sqlparser_databricks.rs
+++ b/tests/sqlparser_databricks.rs
@@ -366,3 +366,17 @@ fn data_type_timestamp_ntz() {
s => panic!("Unexpected statement: {s:?}"),
}
}
+
+#[test]
+fn parse_table_time_travel() {
+ all_dialects_where(|d| d.supports_timestamp_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(
+ "SELECT 1 FROM t1 TIMESTAMP AS OF CURRENT_TIMESTAMP() - INTERVAL 12
HOURS",
+ );
+
+ assert!(databricks()
+ .parse_sql_statements("SELECT 1 FROM t1 FOR TIMESTAMP AS OF
'some_timestamp'")
+ .is_err());
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]