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

   ### SUMMARY
   
   The semantic-layer SDK in `superset-core` publishes its value types but not 
the rules that govern them. Member identity, grain-variant choice, NULL 
semantics in filters and ordering-before-limit are all left implicit, so each 
provider and several host modules re-derive them, and the same rule has 
recently been fixed in more than one place at a time.
   
   This writes each rule down once, in the docstring of the type that owns it. 
No behavior changes.
   
   - **`Metric` / `Dimension` — member identity.** `name` is the stable 
selection key that saved charts and API payloads reference; `verbose_name` is 
display only and excluded from equality; `id` is provider-private and no host 
code reads it. The two kinds of uniqueness are now distinguished explicitly, 
because conflating them is misleading: in the *catalog*, dimensions are unique 
per `(name, grain)`, so several grain variants sharing one name are expected 
and supported, while metric names are unique on their own and must not collide 
with a dimension name; in a *query*, at most one variant per name is selected, 
so a result carries one column per selected member name.
   - **`Grains` — grain-variant selection.** When a selection does not name an 
explicit supported grouping grain, one variant has to be chosen, and the 
preference is: the raw variant, then the finest known grain (second through 
year), then any remaining representation in lexical order. The docstring also 
records why grains must not be sorted by `Grain.name` — alphabetically "Day" 
precedes "Hour" and "Quarter" precedes "Week", the opposite of fineness. 
Routing every host lookup through that single preference is the work of #44454; 
until that lands, some call sites still choose their own way, so the text says 
a provider should not rely on which variant a given lookup picks today.
   - **`Operator` — NULL in filters.** `None` is not a valid comparison 
operand: `= NULL`, `!= NULL`, `IN (NULL)` and `NOT IN (NULL)` are never true in 
SQL, so a provider that renders or binds one silently drops every row the user 
asked for, with no error. Nullness is expressed with `IS_NULL`/`IS_NOT_NULL`, 
and an empty `IN` has no well-defined rendering either. Splitting a `None` 
operand out into those predicates is the host's responsibility and is being 
added separately, so the text tells a provider that already handles `None` 
correctly to keep doing so until then — the docstring is deliberately not an 
invitation to delete working provider-side handling.
   - **`SemanticQuery` and `SemanticView.get_table` — ordering before limit.** 
`order` applies to the full result set before `offset` and `limit`; truncating 
first and sorting the page returns a different and wrong answer.
   
   It also adds `superset.semantic_layers.members.members_by_key`, so member 
identity has one owner in the host instead of being re-derived at each lookup, 
and uses it at the mapper's three name-keyed lookups. The helper reproduces the 
existing comprehension exactly — the mappings it returns are byte-identical, 
including last-wins on duplicate names and insertion order — and a test pins 
that equivalence. It deliberately takes an iterable of members rather than the 
view, so `get_metrics()`/`get_dimensions()` are still called exactly once each 
and the mapper can keep reusing the dimension set for the grain-variant loop 
below.
   
   Narrowing those lookups let MyPy see that `ValidatedQueryObject` declared 
`metrics` wider than `_validate_metrics` permits, so the invariant that 
validation already enforces is now recorded on the class, next to the same 
narrowing already present for `filter`. That is an annotation only, with no 
runtime effect.
   
   Providers that do not currently follow the documented rules are deliberately 
left alone; they are tracked separately rather than fixed here.
   
   ### TESTING INSTRUCTIONS
   
   This change is documentation plus a behavior-preserving extraction, so the 
test of record is that the existing semantic-layer behavior is unchanged and 
the extraction is provably equivalent.
   
   ```bash
   # Full semantic-layer unit suite, with the 100% coverage gate for that 
package
   pytest tests/unit_tests/semantic_layers/ \
     --cov=superset/semantic_layers/ --cov-report=term-missing 
--cov-fail-under=100
   
   # The new helper's own tests, including the equivalence guard
   pytest tests/unit_tests/semantic_layers/members_test.py
   ```
   
   Expected: the semantic-layer suite passes (811 tests locally) with 
`superset/semantic_layers` at 100% statement and branch coverage, and 
`members_test.py` passes 5 tests. `test_matches_the_lookup_it_replaces` is the 
one to read first: it asserts that `members_by_key` produces the same mapping 
*and* the same key order as the dict comprehension it replaces, which is what 
makes the three mapper substitutions safe.
   
   To review the documentation itself, read the four docstrings against the 
code they describe: `Metric`/`Dimension` and `Grains` in 
`superset-core/src/superset_core/semantic_layers/types.py`, `Operator` and 
`SemanticQuery` in the same file, and the `SemanticView` class docstring in 
`view.py`.
   
   The whole `tests/unit_tests` suite was also run: 22420 passed, with only 
pre-existing environment failures unrelated to this change (two arm64 
long-double tests and one translations script test that needs `python` on a 
restricted `PATH`), each confirmed to fail identically on the base commit.
   
   ### ADDITIONAL INFORMATION
   
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] 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
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   The documented rules concern code reached only with the `SEMANTIC_LAYERS` 
feature flag enabled, but nothing here changes flag behavior or adds a flag. 
The `superset-core` changes are docstrings only, so the published SDK surface 
is unchanged; `members_by_key` is an internal host helper, not a new public API.
   
   🤖 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