diff --git a/src/dialect/databricks.rs b/src/dialect/databricks.rs index 3bc187a7f..955761c0c 100644 --- a/src/dialect/databricks.rs +++ b/src/dialect/databricks.rs @@ -15,7 +15,11 @@ // specific language governing permissions and limitations // under the License. +use crate::ast::Expr; use crate::dialect::Dialect; +use crate::parser::{Parser, ParserError}; + +use super::SparkSqlDialect; /// A [`Dialect`] for [Databricks SQL](https://www.databricks.com/) /// @@ -113,4 +117,38 @@ impl Dialect for DatabricksDialect { fn supports_select_item_multi_column_alias(&self) -> bool { true } + + /// See + fn supports_create_table_using(&self) -> bool { + SparkSqlDialect {}.supports_create_table_using() + } + + /// `LONG` is an alias for `BIGINT` in Databricks SQL. + /// + /// See + fn supports_long_type_as_bigint(&self) -> bool { + SparkSqlDialect {}.supports_long_type_as_bigint() + } + + /// See + fn supports_map_literal_with_angle_brackets(&self) -> bool { + SparkSqlDialect {}.supports_map_literal_with_angle_brackets() + } + + /// See + fn supports_pipe_operator(&self) -> bool { + SparkSqlDialect {}.supports_pipe_operator() + } + + /// Parse the `DIV` keyword as integer division. + /// + /// See + fn parse_infix( + &self, + parser: &mut Parser, + expr: &Expr, + precedence: u8, + ) -> Option> { + SparkSqlDialect {}.parse_infix(parser, expr, precedence) + } } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 0800bc41f..b131a1014 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -17318,7 +17318,7 @@ fn parse_pipeline_operator_negative_tests() { // Test that CALL with invalid function syntax fails assert!(dialects - .parse_sql_statements("SELECT * FROM users |> CALL 123invalid") + .parse_sql_statements("SELECT * FROM users |> CALL 123") .is_err()); // Test that CALL with malformed arguments fails @@ -19679,3 +19679,35 @@ fn parse_function_arg_call_chain_no_exponential_blowup() { rx.recv_timeout(Duration::from_secs(5)) .expect("parser should reject this quickly, not loop exponentially"); } + +#[test] +fn parse_create_table_using() { + let sql = "CREATE TABLE t (id BIGINT) USING DELTA"; + all_dialects_where(|d| d.supports_create_table_using()).verified_stmt(sql); + + let unsupported_dialects = all_dialects_where(|d| !d.supports_create_table_using()); + assert!(unsupported_dialects.parse_sql_statements(sql).is_err()); +} + +#[test] +fn parse_map_type_with_angle_brackets() { + let sql = "CREATE TABLE t (m MAP)"; + all_dialects_where(|d| d.supports_map_literal_with_angle_brackets()).verified_stmt(sql); + + let unsupported_dialects = + all_dialects_where(|d| !d.supports_map_literal_with_angle_brackets()); + for dialect in unsupported_dialects.dialects { + assert!(TestedDialects::new(vec![dialect]) + .parse_sql_statements(sql) + .is_err()); + } +} + +#[test] +fn parse_long_type_as_bigint() { + all_dialects_where(|d| d.supports_long_type_as_bigint()) + .one_statement_parses_to("CREATE TABLE t (id LONG)", "CREATE TABLE t (id BIGINT)"); + + let unsupported_dialects = all_dialects_where(|d| !d.supports_long_type_as_bigint()); + unsupported_dialects.verified_stmt("CREATE TABLE t (id LONG)"); +} diff --git a/tests/sqlparser_databricks.rs b/tests/sqlparser_databricks.rs index 7c582546f..bdddadd52 100644 --- a/tests/sqlparser_databricks.rs +++ b/tests/sqlparser_databricks.rs @@ -737,3 +737,62 @@ fn parse_cte_without_as() { .parse_sql_statements("WITH cte (SELECT 1) SELECT * FROM cte") .is_err()); } + +#[test] +fn parse_create_table_using() { + match databricks().verified_stmt("CREATE TABLE t (id BIGINT) USING DELTA") { + Statement::CreateTable(CreateTable { hive_formats, .. }) => { + assert_eq!( + hive_formats.unwrap().storage, + Some(HiveIOFormat::Using { + format: Ident::new("DELTA") + }) + ); + } + s => panic!("Unexpected statement: {s:?}"), + } + + databricks().verified_stmt("CREATE TABLE IF NOT EXISTS t (id BIGINT) USING PARQUET"); +} + +#[test] +fn parse_create_table_map_type() { + match databricks().verified_stmt("CREATE TABLE t (m MAP)") { + Statement::CreateTable(CreateTable { columns, .. }) => { + assert_eq!( + columns[0].data_type, + DataType::Map( + Box::new(DataType::String(None)), + Box::new(DataType::Int(None)), + MapBracketKind::AngleBrackets + ) + ); + } + s => panic!("Unexpected statement: {s:?}"), + } + + databricks().verified_stmt("CREATE TABLE t (m MAP>)"); +} + +#[test] +fn parse_long_type_as_bigint() { + match databricks() + .one_statement_parses_to("CREATE TABLE t (id LONG)", "CREATE TABLE t (id BIGINT)") + { + Statement::CreateTable(CreateTable { columns, .. }) => { + assert_eq!(columns[0].data_type, DataType::BigInt(None)); + } + s => panic!("Unexpected statement: {s:?}"), + } +} + +#[test] +fn parse_div_operator() { + databricks().one_statement_parses_to("SELECT 10 div 3", "SELECT 10 DIV 3"); + databricks().one_statement_parses_to("SELECT c1 div c2 FROM t", "SELECT c1 DIV c2 FROM t"); +} + +#[test] +fn parse_pipe_operator() { + databricks().verified_stmt("SELECT * FROM t |> WHERE x > 1 |> SELECT x AS y |> ORDER BY y"); +}