feat(datasets): add the partition filter mapping editor UI and docs - #43891
Open
hughhhh wants to merge 4 commits into
Open
feat(datasets): add the partition filter mapping editor UI and docs#43891hughhhh wants to merge 4 commits into
hughhhh wants to merge 4 commits into
Conversation
Contributor
|
Bito Automatic Review Skipped - Branch Excluded |
This was referenced Sep 4, 2026
✅ Deploy Preview for superset-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
hughhhh
requested review from
michael-s-molina,
rusackas,
sadpandajoe and
villebro
as code owners
September 4, 2026 21:03
hughhhh
force-pushed
the
hughhhh/pfm-5-editor-ui
branch
from
September 4, 2026 21:03
e51df8a to
240191d
Compare
Fourth of four. Covers configuration, the operator matrix, and the parts a reader will reasonably assume the feature covers but it does not. Two sections carry most of the weight. "Transform preserves ordering" explains why the checkbox exists at all, with `hour()` as the worked example -- it is a perfectly reasonable partition transform and mirroring a range through it returns wrong numbers. And "The assumption this rests on" states the invariant plainly: Superset emits a predicate on the partition column standing in for one on the mapped column, which is only valid if the ETL keeps the two in step. Superset cannot verify that, and when it breaks the result is quietly wrong charts rather than an error, so the docs say so rather than letting people discover it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fifth of the stack, and the one that makes the feature reachable: until now a
mapping could only be configured with a PUT, and the preview endpoint had no
caller. Implements wireframes 1a, 1b, 1c, 1g and 1h.
Two places where the spec and the merged backend disagreed, resolved rather
than papered over:
- The mockups have no monotonicity control, but the query path only mirrors
ranges when the transform is declared order-preserving -- so 1d/1e's own
example, a time range producing two `dt_epoch` bounds, was unreachable
through the UI. Adds the checkbox the shipped docs already describe.
- `unix_timestamp(:value)` is Hive syntax and the PRD asks for it as the
temporal default. Pre-filling it on Postgres or BigQuery would hand the
owner an expression that cannot parse, so the default moves to the engine
spec (`partition_value_transform_default`, set on Hive/Impala/Spark) and
engines without one offer no pre-fill at all.
The preview endpoint now takes `sample_values` plus an operator and builds its
predicate with `build_mirrored_predicates` -- the same function the query path
uses -- so what the panel shows is what a chart emits, `IN` included. It also
accepts a candidate `partition_column`: the editor previews a mapping the owner
has not saved yet, and a preview that requires saving first is not a preview.
Failed probes now carry the engine's own message through an opt-in `errors`
sink, because sqlglot parses unknown functions happily and a misspelled one is
otherwise reported as an unexplained blank.
Two read-path gaps this uncovered, both silent:
- `columns.partition_value_transform` and its monotonic flag were in the
model, the export fields and the PUT schema but not in `show_columns`, so
the editor reopened a saved mapping as if it had none -- and the next save
wrote that emptiness back. Related-model fields have to be listed in
`show_columns`, not only `show_select_columns`.
- `partition_value_transform_default` needed the same treatment to reach the
pre-fill.
Both are now pinned by tests in the serialization suite, whose whole premise is
that a field missing from any one layer is dropped without a sound.
`Field` gains an opt-in `passItemToControl`: the row-expand section keys off the
whole column record, not just the transform it edits, and handing an unknown
`item` prop to every TextControl and Select was not worth the convenience.
Verified against a partitioned table in Docker: the editor configures a mapping,
"View query" carries `dt_epoch >= ... AND dt_epoch < ...` alongside the
`event_time` bounds, a non-temporal `country -> region_key` mapping emits
`region_key IN ('us', 'ca')`, and with the flag off the controls disappear, the
preview endpoint 404s and no predicate is added.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three defects a second pass through the running editor turned up, none of
which unit tests could have caught -- they are all layout or heuristic.
The engine's own error text is the longest string this panel ever shows and its
length is not ours to control. Two things clipped it:
- An expanded antd row sizes to its content, so a long line widened the whole
table and pushed the alert and "Remove mapping" past the modal edge. A zero
max-width on the expanded cell is the standard fix.
- Alert descriptions are `white-space: nowrap` in this theme, so no amount of
width would have wrapped one; the message truncated mid-sentence at
"...stays inactive u". Overridden locally, along with `min-width: 0` on the
flex children, which otherwise refuse to shrink.
Separately, "Map a column →" navigated to whichever column sorted first, which
on the demo table was `revenue` -- inviting the owner to mirror a currency
metric onto a region key. It now prefers a temporal column, since a time range
is what the feature exists for, and falls back to the first non-partition
column only when there is no temporal one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The page sent operators to the dataset editor's **Settings** tab. The controls are in the **Columns** tab, under Default Column Settings -- alongside the default datetime and currency code selects, which is also where wireframe 1a puts them. Someone following this would have clicked Settings and found nothing. Also says where the "Transform preserves ordering" checkbox is, which the page described without ever locating. Found by walking the page against the running editor rather than re-reading it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
hughhhh
force-pushed
the
hughhhh/pfm-5-editor-ui
branch
from
September 4, 2026 21:13
240191d to
de8d5b7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SUMMARY
Fourth of the partition filter mapping stack, and the PR that makes the feature reachable. Until now a mapping could only be configured with a
PUT /api/v1/dataset/<pk>, and the preview endpoint added in the previous PR had no caller — its own commit message says the visual controls "are not in this PR". This implements them: wireframes 1a, 1b, 1c, 1g, 1h.Includes the documentation (
docs/admin_docs/configuration/partition-filter-mapping.mdx, originally #43760, now closed). The two are combined deliberately: that page tells operators to pick a Partition column in the dataset editor and refers to "the editor's preview panel", so shipping it ahead of these controls would publish instructions for things that do not exist yet. Merging them together removes that window entirely.Stacked on
hughhhh/pfm-3-preview-and-editor. Review the compare against pfm-3 rather than the diff against master.What's new in the editor
partition_mapped_column ?? main_dttm_col, and a second select would let it drift from the default datetime column silently.PARTITIONtag, and defaultsIs filterable/Is dimensionoff — still manually togglable.Two places the spec and the merged backend disagreed
dt_epochbounds) was unreachable through the UI. This adds the Transform preserves ordering checkbox that the docs in pfm-4 already describe.unix_timestamp(:value)as the temporal default, but that's Hive syntax and would not parse on Postgres, Trino or BigQuery. The default moves to the engine spec (partition_value_transform_default, set on Hive/Impala/Spark); engines without one offer no pre-fill rather than a wrong one.Backend changes
sample_values+ anoperatorand builds its predicate withbuild_mirrored_predicates— the same function the query path uses — so what the panel shows is what a chart emits,INincluded. It also accepts a candidatepartition_column, because the editor previews a mapping the owner hasn't saved yet and a preview that requires saving first isn't a preview.errorssink (the hot query path passes nothing and stays silent). sqlglot parses unknown functions happily, so a misspelled one is an engine error and was previously reported as an unexplained blank.SELECTprefix and the:value→NULLsubstitution so it points at what the owner actually typed.Two silent read-path bugs this uncovered
Neither was reachable from unit tests; both needed the running app.
columns.partition_value_transformand its monotonic flag were in the model, the export fields and the PUT schema but not inshow_columns— so the editor reopened a saved mapping as if it had none, and the next save wrote that emptiness back. Related-model fields must be listed inshow_columns, not onlyshow_select_columns(columns.advanced_data_typeis in both for the same reason).partition_value_transform_defaultneeded the same treatment to reach the pre-fill.Both are now pinned by tests in
partition_mapping_serialization_test.py, whose whole premise is that a field missing from any one layer is dropped without a sound.One small shared change:
Fieldgains an opt-inpassItemToControl. The row-expand section keys off the whole column record, not just the transform it edits, and handing an unknownitemprop to everyTextControlandSelectwasn't worth the convenience.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Screenshots captured during validation; attaching separately.
1aPartition column + Maps to partition, and1bthe mutedPARTITIONrow1cRow expand with transform, ordering checkbox and a valid preview1cParse error state — only one of preview/error is ever visible1gPartition column set with nothing mapped1hNon-temporalcountry → region_keyTESTING INSTRUCTIONS
Automated:
1800backend unit tests and225frontend Datasource tests pass;tsc,ruff,ruff formatandoxlintare clean (oxlint warnings insrc/components/Datasourcego 32 → 30, since the duplicated column-name renderer was folded into one helper).Manually, against a real engine:
FEATURE_FLAGS = {"PARTITION_FILTER_MAPPING": True}.dt_epoch. Confirm Maps to partition showsevent_timetagged Default datetime column, and thatdt_epoch's row is muted with aPARTITIONtag and its toggles off.cast(extract(epoch from cast(:value as timestamp)) as bigint)and check Transform preserves ordering. The preview should readevent_time >= '2026-01-15 00:00:00'→dt_epoch >= 1768435200. Unchecking it drops the preview back to=.lower(:value))) → Can't parse transform with a position, and the preview panel disappears.region_key, move the mapping tocountry, setlower(:value). Preview showscountry IN ('US', 'CA')→region_key IN ('us', 'ca'), and a chart filtered oncountryemitsAND region_key IN ('us', 'ca').Known limitation, not introduced here: SQLAlchemy's
text()misparses Postgres::casts, so a transform written as:value::timestampleaves the placeholder unbound. This comes frombuild_probe_sqlin pfm-2 and is harmless on Hive/Impala, which have no::syntax — the ANSIcast(:value as timestamp)form works. Worth a follow-up for Postgres/Redshift users.ADDITIONAL INFORMATION
PARTITION_FILTER_MAPPING🤖 Generated with Claude Code
How Has This Been Tested?
Validated against the full stack under Docker (Flask + Celery worker + Postgres + Redis) serving this branch, driving the real browser. Two rounds: once during implementation, once after pushing — the second round found the three defects fixed in
8f873f3.Bring-up (non-default ports, since 8088/5432 are usually taken by another stack):
Fixture — a table where the partition key really is the transform of the business column, so a mirrored predicate is verifiably correct rather than merely present:
The walk (543 rows, 5 columns):
00-before-no-partition-column.png— Partition columnNone, no Maps to partition, all rows normaldt_epoch01-1a-1b-partition-column-selected.png— Maps to partition →event_timetagged Default datetime column;dt_epochrow muted withPARTITIONtag and its three toggles off, every other row untouched02-1c-row-expand-valid-preview.png— previewevent_time >= '2026-01-15 00:00:00'→dt_epoch >= 1768435200. Unticking drops it back to=lower(:value)))03-1c-parse-error.png— Can't parse transform, syntax error at position 14, preview hidden (only one of preview/error is ever visible)04-1g-partition-column-no-mapping.png—No mappingchip, Map a column →, and the scan-every-partition warningregion_key, move the mapping tocountry,lower(:value)05-1h-non-temporal-mapping.png— required asterisk,country IN ('US', 'CA')→region_key IN ('us', 'ca')Screenshots live in
.context/pfm-ui-screenshots/(gitignored) and are attached above.Non-visual proof. The generated SQL, via
/api/v1/chart/datawithresult_type: query— the same SQL the View query panel renders:1782864000is exactly2026-07-01T00:00:00Z, matching how the fixture populatesdt_epoch— so the pruning predicate selects the same rows rather than merely looking plausible.Negative case — with
PARTITION_FILTER_MAPPINGoff: the Partition column field, thePARTITIONtag and the muted row all disappear, the preview endpoint returns 404, and the same query emits noregion_keypredicate at all.Also verified the engine-specific default behaves: on Postgres
partition_value_transform_defaultisNone, so the editor offers no pre-fill rather than a Hive expression that would not parse.What the browser pass caught that tests did not
Worth calling out, since it's the argument for doing this at all:
show_columns, so reopening showed an empty transform and the next save persisted that emptiness. Fixed, and pinned by tests.8f873f3: the engine's error text clipped mid-sentence (expanded antd rows size to content, and alert descriptions arenowrapin this theme), and Map a column → suggestingrevenue— inviting an owner to mirror a currency metric onto a region key.Additionally verified (third pass)
GET /api/v1/explore/?datasource_type=table&datasource_id=…) carriesregion_key: {groupby: false, filterable: false}while every other column staystrue;dndControls.tsxbuilds the Dimensions options fromcolumns.filter(c => c.groupby)and the Filters options fromcolumns.filter(c => c.filterable). Both ends verified against the running app. I could not get the drag-and-drop popover itself to open under automation, so this rests on the payload plus Superset's existing filter rather than on my having seen the rendered list.region_keyfrom the physical table with the mapping live, then hit Sync columns from source: three toasts fire —Metadata has been synced,The partition filter mapping was cleared: its column is gone,Removed 1 column from the virtual dataset— the Columns badge goes 5 → 4, and Partition column resets toNonewith Maps to partition gone.06-sync-clears-dangling-mapping.pngcaptures the resulting state (the toasts auto-dismiss before a screenshot lands; the strings above are read straight from the DOM).Wireframe 1e in the real panel
View query shows the mirrored predicate as an ordinary
WHEREclause, exactly as 1e specifies — captured in07-1e-view-query-mirrored-predicate.png:Docs verified by building the site
yarn buildindocs/succeeds (EXIT=0) and emitsbuild/admin-docs/configuration/partition-filter-mapping/index.html. Served and walked in a browser: title, breadcrumb, sidebar placement under Configuration, the:::cautionadmonition, all three tables and the right-hand TOC render correctly (10-docs-page.png). The newPARTITION_FILTER_MAPPINGentry also surfaces on the Feature Flags page with its default and description, since that page readsstatic/feature-flags.json.This mattered:
superset-docs-verify.ymlrunsyarn buildon every PR, and this page carries an ASF license header as an HTML comment (<!-- -->), which MDX v3 does not accept as a comment. Only two otheradmin_docspages do the same and neither is on master, so nothing proved it was safe. It builds.One factual error the walk caught (fixed in
e51df8a): the page sent operators to the dataset editor's Settings tab. The controls are in the Columns tab under Default Column Settings — confirmed by tab-by-tab visibility checks in the running editor (visible under Columns and Calculated columns, not Settings), and it is where wireframe 1a puts them. Someone following the page would have clicked Settings and found nothing. The same commit says where the Transform preserves ordering checkbox lives, which the page described without ever locating.Known limitation (pre-existing, not introduced here)
SQLAlchemy's
text()misparses Postgres::casts, so a transform written:value::timestampleaves the placeholder unbound and the probe fails with "This text() construct doesn't define a bound parameter named 'value'". It comes frombuild_probe_sqlin pfm-2 and is harmless on Hive/Impala, which have no::syntax. The ANSI formcast(:value as timestamp)works and is what the walk above uses. Worth a follow-up for Postgres/Redshift.