mikebridge opened a new pull request, #42540:
URL: https://github.com/apache/superset/pull/42540

   ### SUMMARY
   
   Semantic-view providers can now declare what their backend supports, and the 
Explore column picker adapts its modes and dimension classification to that 
declaration instead of guessing from column metadata.
   
   **A note on the originating report.** The story this came from (SC-107939) 
describes the "Columns and metrics" picker showing `0 item(s)` for a 
Cube-backed semantic view. That symptom no longer reproduces on master, and 
this PR is not what fixes it. Reproduced against a live Cube instance through 
the real model path: dimensions arrive with `expression=None`, so the picker's 
expression-based split routes all four into Simple, not zero. The empty picker 
was caused by the pre-#41456 payload, which set 
`expression=dimension.definition`; because `ColumnSelectPopover` treats any 
column with a truthy `expression` as a Saved/calculated column, every dimension 
landed in Saved and Simple rendered `0 item(s)`. #41456 (`e28b259de0`) flipped 
that field to `None` for time-grain reasons and incidentally moved the 
dimensions into Simple.
   
   What remains wrong is that Simple is the wrong home for them, and one piece 
of genuinely broken state. This PR addresses both:
   
   **1. Providers declare features; Explore consumes capabilities.** A new 
opt-in `SemanticViewFeature.ADHOC_COLUMN_EXPRESSIONS` marks views whose backend 
accepts simple/custom-SQL column expressions. The declared set serializes to 
the datasource payload as `semantic_view_features`. A view that does not 
declare it gets a Saved-only picker: dimensions listed as Saved options, Simple 
and Custom SQL visible but disabled, so users cannot compose an expression the 
backend would reject.
   
   Polarity is opt-in to match the existing provider convention — Snowflake 
declares its features, Cube and MetricFlow deliberately ship `frozenset()`. A 
companion one-line declaration on `SnowflakeSemanticView` keeps Snowflake's 
picker behavior unchanged and ships separately in the shell repo.
   
   Provider identity is deliberately **not** sent over the wire. The 
`@semantic_layer` decorator prefixes extension IDs 
(`extensions.preset-io.cube-semantic-layer.cube`), so there is no stable bare 
registry key to publish, and behavior keyed off provider identity would not 
survive that prefixing. Features are translated exactly once, in 
`utils/pickerCapabilities.ts`, into a provider-neutral 
`ColumnPickerCapabilities`. Picker components consume capabilities and never 
read feature strings, registry keys, or display names. Two DnD wrappers that 
each carried their own copy of the "semantic views disable Custom SQL" rule now 
defer to that adapter.
   
   **2. Compatibility request state was conflated (a real defect).** 
`fetchCompatibility` dispatched an identical `{compatibleMetrics: null, 
compatibleDimensions: null, compatibilityLoading: false}` both when the 
datasource is non-semantic and when the request *failed*. A failed 
compatibility lookup was therefore indistinguishable from "no filtering 
applies", so no UI could ever surface it. That state is now a discriminated 
`CompatibilityResult` (`idle | loading | verified | failed`) read through typed 
selectors, and every existing consumer — column picker, datasource-panel drag 
options, adhoc metric popover — was migrated in the same change so the 
replacement cannot strand an old reader. Idle, loading, and failed keep the 
existing no-filter fallback; a `verified` empty result is a valid "nothing is 
compatible" answer, not a fallback; `failed` additionally shows an accessible 
non-blocking warning where the capability enables it.
   
   Incompatible or legacy adhoc values can no longer be silently committed: 
Saved becomes the active mode, the legacy value stays inspectable under Custom 
SQL, and Save is disabled with accessible corrective feedback associated to it 
until the user explicitly picks a compatible dimension.
   
   `expression=None` on semantic dimensions is preserved throughout — #41456's 
time-grain behavior is a protected invariant here, not a cleanup opportunity, 
and there is a regression assertion to that effect.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   Not included: rendering a Cube-backed semantic view requires the proprietary 
provider extension, which is not installable in an OSS checkout. Behavior is 
covered by component tests that drive the real picker, and by a local 
reproduction against a Cube instance described below.
   
   ### TESTING INSTRUCTIONS
   
   Automated (no provider extension needed):
   
   ```bash
   # Frontend — picker, wrappers, control entry points, state, selectors, 
adapter
   cd superset-frontend
   npm test -- src/explore/components/controls/DndColumnSelectControl \
               
src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent
 \
               
src/explore/components/controls/MetricControl/AdhocMetricEditPopover \
               src/explore/components/DatasourcePanel \
               src/explore/actions src/explore/reducers src/explore/selectors
   
   # Backend — feature serialization and the #41456 expression/time-grain 
invariant
   pytest tests/unit_tests/semantic_layers/models_test.py
   ```
   
   Manual, with a semantic-layer provider available:
   
   1. Open Explore on a semantic view whose provider declares no features. Open 
an X-axis or Dimensions control: the picker opens on **Saved** listing every 
dimension by verbose name; Simple and Custom SQL are visible but disabled. 
Select one and save — it commits to the control.
   2. Select a metric first so compatibility narrows, then reopen: dimensions 
outside the compatible set are visible but disabled. With no compatible 
dimensions, the picker says so rather than looking like a loading or failed 
state.
   3. Repeat on a view whose provider declares `ADHOC_COLUMN_EXPRESSIONS` (and 
on a plain table dataset): modes, defaults, search, and Save are unchanged.
   4. Repeat through Filter subject and Sort by.
   
   The `0 item(s)` claim above was verified against the Cube fixture in 
`db-infra/databases/cube` (REST API on `:4000`) using a throwaway provider stub 
over `SemanticView.data`; the stub is not part of this PR.
   
   ### ADDITIONAL INFORMATION
   - [x] Has associated issue: SC-107939 (Preset-internal)
   - [ ] Required feature flags:
   - [x] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [x] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   Backwards compatible: `semantic_view_features` is additive and optional. 
Payloads without it, unknown feature strings, and non-semantic datasources all 
resolve to existing behavior, so no `UPDATING.md` entry is needed.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to