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]