mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-12-23 11:12:51 +00:00
Databricks timestamp as of syntax support
This commit is contained in:
parent
1b842d3b6a
commit
8691eadc30
5 changed files with 104 additions and 1 deletions
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15137,6 +15137,11 @@ 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 dialect_of!(self is DatabricksDialect)
|
||||
&& self.parse_keywords(&[Keyword::TIMESTAMP, Keyword::AS, Keyword::OF])
|
||||
{
|
||||
let expr = self.parse_expr()?;
|
||||
return Ok(Some(TableVersion::TimestampAsOf(expr)));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -1753,6 +1753,10 @@ fn parse_table_time_travel() {
|
|||
|
||||
let sql = "SELECT 1 FROM t1 FOR SYSTEM TIME AS OF 'some_timestamp'".to_string();
|
||||
assert!(bigquery().parse_sql_statements(&sql).is_err());
|
||||
|
||||
// The following time travel syntax(es) are invalid in BigQuery dialect
|
||||
let sql = "SELECT 1 FROM t1 TIMESTAMP AS OF '{version}'".to_string();
|
||||
assert!(bigquery().parse_sql_statements(&sql).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -366,3 +366,87 @@ fn data_type_timestamp_ntz() {
|
|||
s => panic!("Unexpected statement: {s:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_table_time_travel() {
|
||||
let version = "2018-10-18T22:15:12.013Z".to_string();
|
||||
let sql = format!("SELECT 1 FROM t1 TIMESTAMP AS OF '{version}'");
|
||||
let select = databricks().verified_only_select(&sql);
|
||||
assert_eq!(
|
||||
select.from,
|
||||
vec![TableWithJoins {
|
||||
relation: TableFactor::Table {
|
||||
name: ObjectName::from(vec![Ident::new("t1")]),
|
||||
alias: None,
|
||||
args: None,
|
||||
with_hints: vec![],
|
||||
version: Some(TableVersion::TimestampAsOf(Expr::Value(
|
||||
Value::SingleQuotedString(version.clone()).with_empty_span()
|
||||
))),
|
||||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
json_path: None,
|
||||
sample: None,
|
||||
index_hints: vec![],
|
||||
},
|
||||
joins: vec![]
|
||||
},]
|
||||
);
|
||||
|
||||
let sql = "SELECT 1 FROM t1 TIMESTAMP AS OF CURRENT_TIMESTAMP() - INTERVAL 12 HOURS".to_string();
|
||||
let select = databricks().verified_only_select(&sql);
|
||||
assert_eq!(
|
||||
select.from,
|
||||
vec![TableWithJoins {
|
||||
relation: TableFactor::Table {
|
||||
name: ObjectName::from(vec![Ident::new("t1")]),
|
||||
alias: None,
|
||||
args: None,
|
||||
with_hints: vec![],
|
||||
version: Some(TableVersion::TimestampAsOf(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Function(Function {
|
||||
name: ObjectName::from(vec![Ident::new("CURRENT_TIMESTAMP")]),
|
||||
uses_odbc_syntax: false,
|
||||
parameters: FunctionArguments::None,
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![],
|
||||
clauses: vec![]
|
||||
}),
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
within_group: vec![]
|
||||
})),
|
||||
op: BinaryOperator::Minus,
|
||||
right: Box::new(Expr::Interval(Interval {
|
||||
value: Box::new(Expr::Value(number("12").into())),
|
||||
leading_field: Some(DateTimeField::Hours),
|
||||
leading_precision: None,
|
||||
last_field: None,
|
||||
fractional_seconds_precision: None,
|
||||
}))
|
||||
})),
|
||||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
json_path: None,
|
||||
sample: None,
|
||||
index_hints: vec![],
|
||||
},
|
||||
joins: vec![]
|
||||
},]
|
||||
);
|
||||
|
||||
let sql = "SELECT 1 FROM t1 FOR TIMESTAMP AS OF 'some_timestamp'".to_string();
|
||||
assert!(databricks().parse_sql_statements(&sql).is_err());
|
||||
|
||||
// The following time travel syntax(es) are invalid in Databricks dialect
|
||||
let sql = "SELECT 1 FROM t1 FOR TIMESTAMP AS OF '{version}'".to_string();
|
||||
assert!(databricks().parse_sql_statements(&sql).is_err());
|
||||
|
||||
let sql = "SELECT 1 FROM t1 AT '{version}'".to_string();
|
||||
assert!(databricks().parse_sql_statements(&sql).is_err());
|
||||
|
||||
let sql = "SELECT 1 FROM t1 BEFORE '{version}'".to_string();
|
||||
assert!(databricks().parse_sql_statements(&sql).is_err());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue