Skip to content

Databricks: support CREATE TABLE USING, MAP<K, V>, LONG, DIV and the pipe operator - #2425

Open
shuvamk wants to merge 2 commits into
apache:mainfrom
shuvamk:databricks-spark-sql-flags
Open

Databricks: support CREATE TABLE USING, MAP<K, V>, LONG, DIV and the pipe operator#2425
shuvamk wants to merge 2 commits into
apache:mainfrom
shuvamk:databricks-spark-sql-flags

Conversation

@shuvamk

@shuvamk shuvamk commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Databricks SQL is built on Spark SQL, but DatabricksDialect was missing flags SparkSqlDialect sets. These fail on DatabricksDialect and parse on SparkSqlDialect:

CREATE TABLE t (id BIGINT) USING DELTA
CREATE TABLE t (m MAP<STRING, INT>)
SELECT 10 div 3
SELECT * FROM t |> WHERE x > 1

CREATE TABLE t (id LONG) parses, but as a DataType::Custom, not DataType::BigInt(None).

div and pipeline syntax are documented for Databricks SQL:
https://docs.databricks.com/aws/en/sql/language-manual/functions/div
https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-qry-pipeline

The methods shared with Spark delegate to SparkSqlDialect rather than repeating the value, the same shape RedshiftSqlDialect uses for PostgreSqlDialect.

parse_pipeline_operator_negative_tests now uses |> CALL 123 instead of 123invalid: enabling the pipe operator brings Databricks into that assertion, and supports_numeric_prefix makes it fail at a different point. Both inputs fail identically on the dialects already covered.

Tests are in tests/sqlparser_databricks.rs and tests/sqlparser_common.rs; the five Databricks ones fail with src/dialect/databricks.rs reverted. The AGENTS.md pre-commit checks are clean locally.

… BIGINT

Databricks SQL is built on Spark SQL, but DatabricksDialect never got
three of the flags SparkSqlDialect sets, so these fail on Databricks and
parse on Spark:

    CREATE TABLE t (id BIGINT) USING DELTA
    CREATE TABLE t (m MAP<STRING, INT>)

with "Expected: end of statement, found: USING at Line: 1, Column: 28"
and "Expected: ',' or ')' after column definition, found: < at Line: 1,
Column: 22".

CREATE TABLE t (id LONG) parses, but builds DataType::Custom("LONG")
instead of DataType::BigInt(None). Databricks documents the type as
{ BIGINT | LONG }.

Set supports_create_table_using, supports_long_type_as_bigint and
supports_map_literal_with_angle_brackets on DatabricksDialect, mirroring
src/dialect/spark.rs. No parser change and no other dialect is affected.

Regression tests in tests/sqlparser_databricks.rs; all three fail with
src/dialect/databricks.rs reverted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread tests/sqlparser_databricks.rs Outdated

databricks().verified_stmt("CREATE TABLE IF NOT EXISTS t (id BIGINT) USING PARQUET");

assert!(all_dialects_where(|d| !d.supports_create_table_using())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding the analogous assert also for the other flags you have set

Comment thread tests/sqlparser_databricks.rs Outdated

databricks().verified_stmt("CREATE TABLE IF NOT EXISTS t (id BIGINT) USING PARQUET");

assert!(all_dialects_where(|d| !d.supports_create_table_using())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I believe that since this assertion regards all dialects except databricks, it should not be in the databricks tests, but in common.

Comment thread src/dialect/databricks.rs
fn supports_long_type_as_bigint(&self) -> bool {
true
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you are adding support for Spark flags in Databricks, I believe you should also add supports_pipe_operator and parse_infix for DIV.

Comment thread src/dialect/databricks.rs
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DatabricksDialect;

impl Dialect for DatabricksDialect {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there is some argument to be made that, since several of these properties need to be kept aligned between Spark and Databricks, it may be desirable to call directly Spark methods in these methods instead of duplicating the scalar value.

Address review feedback on apache#2425.

The flags Databricks shares with Spark now call the Spark methods
instead of repeating the literal, so the two dialects cannot drift
apart silently. `RedshiftSqlDialect` already delegates to
`PostgreSqlDialect` this way.

Two more Spark capabilities are documented for Databricks SQL and were
missing:

  SELECT 10 div 3
  SELECT * FROM t |> WHERE x > 1 |> SELECT x AS y

Both failed with `No infix parser for token Word(... keyword: DIV })`
and `Expected: end of statement, found: |`.
`div` is documented at
https://docs.databricks.com/aws/en/sql/language-manual/functions/div and
pipeline syntax at
https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-qry-pipeline
(Databricks SQL / Databricks Runtime 16.2 and above).

The cross-dialect assertion moves from the Databricks tests to
`tests/sqlparser_common.rs`, joined by the analogous assertions for the
`MAP<K, V>` and `LONG` flags. Dialects that do not set
`supports_map_literal_with_angle_brackets` reject `MAP<STRING, INT>`
with two different messages, so that one is checked per dialect as in
`parse_create_table_exclude_constraint`. Dialects that do not set
`supports_long_type_as_bigint` parse `LONG` as a custom type rather
than erroring, so the assertion there is that the statement round-trips
unchanged.

`parse_pipeline_operator_negative_tests` asserted that
`|> CALL 123invalid` fails with one message across every pipe-enabled
dialect. Databricks sets `supports_numeric_prefix`, so it reads
`123invalid` as an identifier and fails later, on the missing
parentheses. The input is now `|> CALL 123`, which fails identically on
all of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@shuvamk shuvamk changed the title Databricks: support CREATE TABLE USING, MAP<K, V> columns and LONG as BIGINT Databricks: support CREATE TABLE USING, MAP<K, V>, LONG, DIV and the pipe operator Aug 8, 2026
@shuvamk

shuvamk commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks — all four addressed in the follow-up commit.

DIV and |> are both documented for Databricks SQL, so I added them: supports_pipe_operator, and parse_infix delegating to Spark, which handles DIV and nothing else.

On delegating the flags: I converted the ones Spark and Databricks share, but left supports_numeric_prefix, supports_table_versioning and supports_optimize_table as they were — Spark doesn't override those, so delegating would take them from true to the trait default false and stop SELECT 59901_user, VERSION AS OF and OPTIMIZE from parsing on Databricks. Happy to convert the remaining shared ones too if you'd like the whole block consistent.

The cross-dialect asserts moved to tests/sqlparser_common.rs so Databricks is covered, with the flag-off negatives alongside them. MAP<K, V> needed a per-dialect loop rather than one is_err() — the ungated dialects split into two different error messages.

Title and description updated for the added scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants