Skip to content

Databricks: support multipart TABLE queries - #2594

Open
EthanVieira wants to merge 29 commits into
apache:mainfrom
EthanVieira:dbx-split-02-multipart-table-queries
Open

EthanVieira wants to merge 29 commits into
apache:mainfrom
EthanVieira:dbx-split-02-multipart-table-queries

Conversation

@EthanVieira

@EthanVieira EthanVieira commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Allows Databricks TABLE queries to reference multipart names such as main.raw.source.

Reference: Names

@codecov-commenter

codecov-commenter commented Sep 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.55%. Comparing base (9f66d76) to head (7465099).

Files with missing lines Patch % Lines
src/ast/query.rs 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2594   +/-   ##
=======================================
  Coverage   82.54%   82.55%           
=======================================
  Files          42       42           
  Lines       35556    35558    +2     
  Branches    35556    35558    +2     
=======================================
+ Hits        29349    29354    +5     
  Misses       2672     2672           
+ Partials     3535     3532    -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@LucaCappelletti94

Copy link
Copy Markdown
Contributor

@EthanVieira please do add an entry to the fuzzer seed corpus with this syntax if there isn't one already

@LucaCappelletti94 LucaCappelletti94 added the waiting on contributor The review needs further refinements by its author label Sep 28, 2026
@LucaCappelletti94 LucaCappelletti94 added waiting on reviewer PR needs to be reviewed and removed waiting on contributor The review needs further refinements by its author labels Sep 28, 2026

@LucaCappelletti94 LucaCappelletti94 left a comment

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 that we need to make the Table struct hold an ObjectName, as TableFactor::Table does, so a qualified name of any length keeps its parts.

@@ -300,6 +300,4 @@ impl fmt::Display for SetQuantifier {
 pub struct Table {
-    /// Optional table name (absent for e.g. `TABLE` command without argument).
-    pub table_name: Option<Ident>,
-    /// Optional schema/catalog name qualifying the table.
-    pub schema_name: Option<Ident>,
+    /// Optional, possibly qualified, table name (absent for e.g. `TABLE` command without argument).
+    pub name: Option<ObjectName>,
 }

This of course will call for several changes both in the repo and downstream, but it seems like the cleanest solution to me. @alamb opinions?

Comment thread src/parser/mod.rs Outdated
Comment on lines 15772 to 15818

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.

You should keep every name part as its own Ident instead of joining the qualifiers into one. As written, main.raw.source and `main.raw`.source both give a schema_name whose value is "main.raw", and `a b`.raw.source gives the value "`a b`.raw" with the backticks inside it, so consumers cannot recover the parts. This relies on the Table change in the global note.

Suggested change
let max_parts = if self.dialect.supports_multipart_table_query_name() {
usize::MAX
} else {
2
};
let mut parts = vec![self.parse_identifier()?];
while parts.len() < max_parts && self.consume_token(&Token::Period) {
parts.push(self.parse_identifier()?);
}
Ok(Table {
name: Some(ObjectName::from(parts)),
})

Comment thread tests/sqlparser_databricks.rs Outdated

#[test]
fn parse_databricks_multipart_table_query() {
databricks().verified_stmt("CREATE VIEW copy AS TABLE main.raw.source");

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.

You should assert the parsed parts, because verified_stmt only checks the round trip and the joined Ident passes it.

Suggested change
databricks().verified_stmt("CREATE VIEW copy AS TABLE main.raw.source");
let Statement::CreateView(view) =
databricks().verified_stmt("CREATE VIEW copy AS TABLE main.raw.source")
else {
unreachable!()
};
assert_eq!(
*view.query.body,
SetExpr::Table(Box::new(Table {
name: Some(ObjectName::from(vec![
Ident::new("main"),
Ident::new("raw"),
Ident::new("source"),
])),
}))
);

LucaCappelletti94 and others added 21 commits October 16, 2026 08:00
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#2638)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…e#2626)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
dependabot Bot and others added 6 commits October 16, 2026 08:00
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…t-table-queries

# Conflicts:
#	docs/fuzzing.md
#	fuzz/Cargo.toml
#	src/ast/mod.rs
#	src/ast/spans.rs
#	src/dialect/duckdb.rs
#	src/dialect/mod.rs
#	src/parser/mod.rs
#	tests/sqlparser_clickhouse.rs
#	tests/sqlparser_common.rs
#	tests/sqlparser_custom_dialect.rs
#	tests/sqlparser_databricks.rs
#	tests/sqlparser_duckdb.rs
#	tests/sqlparser_mysql.rs
#	tests/sqlparser_postgres.rs
#	tests/sqlparser_sqlite.rs
@EthanVieira

Copy link
Copy Markdown
Contributor Author

I believe that we need to make the Table struct hold an ObjectName, as TableFactor::Table does, so a qualified name of any length keeps its parts.

@@ -300,6 +300,4 @@ impl fmt::Display for SetQuantifier {
 pub struct Table {
-    /// Optional table name (absent for e.g. `TABLE` command without argument).
-    pub table_name: Option<Ident>,
-    /// Optional schema/catalog name qualifying the table.
-    pub schema_name: Option<Ident>,
+    /// Optional, possibly qualified, table name (absent for e.g. `TABLE` command without argument).
+    pub name: Option<ObjectName>,
 }

This of course will call for several changes both in the repo and downstream, but it seems like the cleanest solution to me. @alamb opinions?

Haven't heard from @alamb, but I went ahead and did this.

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

Labels

Databricks waiting on reviewer PR needs to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants