fix(data-diff): restore Table Diff on Databricks, Unity Catalog and AzureSQL - #31356
Conversation
…thType DatabricksBaseTableParameter built the data-diff URL by reading a top-level 'token' attribute that neither connection schema has - both nest it under authType - so the URL always carried an empty password. data-diff maps that password to access_token, the SQL connector drops a falsy one, and auth selection then falls through to the interactive OAuth provider, which parks a headless agent on a browser redirect that never arrives. Every tableDiff on either connector hung until it was killed by hand. Describe the connection to data-diff as a dict instead, built by the connection class from authType and carrying an auth_method discriminator, so all three authentication types are expressed in full and none is reduced to a partial credential. The param setter now injects the catalog and schema of each table, which the URL form used to supply and a service-level dict cannot. Also copy the connection dict before rewriting its driver: both sides of a same-service diff are handed the same object.
The test-case form lists test definitions filtered by supportedService, and tableDiff omitted both connectors, so the test could only be created through the REST API even though each ships a data diff parameter setter.
AzureSQL ships its own data diff parameter setter but its service type was never added to the allowlist, so the test was unreachable from the UI for the same reason as Databricks and Unity Catalog.
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
The scheme guard called the removed URL builder with a config carrying a top-level token, a shape neither connection schema has ever had. Assert the driver on the connection dict instead, which is where the scheme now lives.
✅ Playwright Results — workflow succeededValidated commit ✅ 613 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 26m 58s ⏱️ Max setup 3m 14s · max shard execution 17m 58s · max shard-job elapsed before upload 21m 17s · reporting 5s 🌐 217.27 requests/attempt · 2.75 app boots/UI scenario · 5.29% common-shard skew Optimization targets still in progress:
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
Code Review ✅ ApprovedRestores Table Diff on Databricks, Unity Catalog, and AzureSQL by reading connection credentials from authType and updating supported services. No issues found. OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |
…zureSQL (#31356) (#31377) * fix(data-diff): read Databricks and Unity Catalog credentials from authType DatabricksBaseTableParameter built the data-diff URL by reading a top-level 'token' attribute that neither connection schema has - both nest it under authType - so the URL always carried an empty password. data-diff maps that password to access_token, the SQL connector drops a falsy one, and auth selection then falls through to the interactive OAuth provider, which parks a headless agent on a browser redirect that never arrives. Every tableDiff on either connector hung until it was killed by hand. Describe the connection to data-diff as a dict instead, built by the connection class from authType and carrying an auth_method discriminator, so all three authentication types are expressed in full and none is reduced to a partial credential. The param setter now injects the catalog and schema of each table, which the URL form used to supply and a service-level dict cannot. Also copy the connection dict before rewriting its driver: both sides of a same-service diff are handed the same object. * fix(data-quality): offer Table Diff on Databricks and Unity Catalog The test-case form lists test definitions filtered by supportedService, and tableDiff omitted both connectors, so the test could only be created through the REST API even though each ships a data diff parameter setter. * fix(data-quality): offer Table Diff on AzureSQL AzureSQL ships its own data diff parameter setter but its service type was never added to the allowlist, so the test was unreachable from the UI for the same reason as Databricks and Unity Catalog. * test(data-diff): assert the Databricks scheme on the connection dict The scheme guard called the removed URL builder with a config carrying a top-level token, a shape neither connection schema has ever had. Assert the driver on the connection dict instead, which is where the scheme now lives. (cherry picked from commit d302bfa)
Describe your changes:
Fixes #
Table Diff has been broken on Databricks and Unity Catalog since two unrelated changes landed in late 2025, and unreachable from the UI on AzureSQL since the second of them.
The run never returned.
DatabricksBaseTableParameterbuilt the data-diff URL fromgetattr(service_connection_config, "token", ""). #23561 movedtokenunderauthTypeon both connection schemas and touched no data-diff file, so from that commit the default kicked in and the URL carried an empty password. data-diff maps that password toaccess_token;databricks-sql-connectordrops a falsy one (client.py:274), auth selection falls through toDatabricksOAuthProvider, and a headless agent parks on a browser redirect that never arrives. EverytableDiffon either connector hung until it was killed by hand.The test was not offered in the UI. #24706 introduced
supportedServicesontableDiff.json. The filter treats an absent list as "all services" (CollectionDAO.java:9079-9081), so adding an allowlist that omits Databricks, UnityCatalog and AzureSQL revoked the test from three connectors that each ship a data-diff parameter setter.Type of change:
High-level design:
The connection is now described to data-diff as a dict built by the connection class, instead of a hand-spliced URL:
get_data_diff_connection_dictlives indatabricks/auth.pynext toget_auth_config, and bothDatabricksConnectionandUnityCatalogConnectionexpose it throughget_connection_dict(). All three authentication types are expressed in full — personal access token, Databricks OAuth M2M, and Azure AD service principal — so none is reduced to a partial credential. Every value is a plain string, because data-diff caches connections onjson.dumpsof the config; providers are constructed on its side (open-metadata/collate-data-diff#33), which is why this PR floorscollate-data-diff>=0.11.15.A service-level dict cannot carry the catalog, and data-diff resolves a two-part
schema.tablepath against the connection's catalog (defaulting tohive_metastore).DatabricksBaseTableParametertherefore injects the catalog and schema of each table, following the shapeTrinoTableParameterandAzureSQLTableParameteralready use. This also makes a cross-catalog diff on one service resolve each side independently.The URL form was kept in an earlier draft and rejected: it cannot express Azure AD at all, and string-splicing credentials into an authority is what produced the original bug.
base_diff_params_setternow copies the connection dict before rewriting its driver — both sides of a same-service diff are handed the same object, so in-place mutation would let one side's scope overwrite the other's.Rollout:
Blocked on the
collate-data-diff0.11.15 release; draft until then. The break has been present since 2025-10-03, so this likely warrants a backport to the active release lines as well as main.