Repository navigation
test(compliance): add portability measurement fixtures M0-M3 (#576) - #596
MrBlack1995 wants to merge 2 commits into
Conversation
kayemkim
left a comment
There was a problem hiding this comment.
I ran all eight fixtures through the same nine converters as the hello-world run, on current main (64a1ae4). 66 documents came back (thoughtspot refused six exports) and every one of them passes validate.py, including the two below that changed meaning.
| converter | M0 ansi | M0 ossie | M0 bare | M1 field | M2 qual | M2 bare | M3 qual | M3 bare |
|---|---|---|---|---|---|---|---|---|
| cube | kept | kept, tag kept | requalified | kept | kept | requalified | kept | requalified |
| dbt | kept | relabeled ANSI | requalified | kept | COUNT rewritten | requalified, COUNT rewritten | SUM(SUM(...)) | SUM(SUM(...)) |
| omni | kept | dropped, warned | requalified | kept | kept | requalified | kept | kept bare |
| sigma | SIGMA + quoted ANSI | dropped, warned | dropped as cross-dataset | SIGMA + quoted | SIGMA + quoted | dropped x6 | SIGMA + quoted | dropped |
| wisdom | kept | relabeled ANSI | kept, warned | kept | kept | kept | kept | kept |
| orionbelt | quoted | relabeled, quoted | +1 helper metric | field renamed to its expression | quoted | +6 helper metrics | quoted | +1 helper metric |
| honeydew | kept | relabeled, warned | kept | kept | kept, reordered | kept, reordered | kept | kept |
| microsoft | DAX only | DAX only | DAX only | BLANK() | DAX only | DAX only | BLANK() | BLANK() |
| thoughtspot | THOUGHTSPOT only | rejected | rejected | rejected | THOUGHTSPOT only | rejected | rejected | rejected |
One thing on the fixtures themselves. The three M0 metrics carry no datatype and every metric from M1 up carries one, so M1 changes two things against M0, and thoughtspot's TS-MODEL-METRIC-DATATYPE-UNWRITABLE warning shows up on M1 for a reason that has nothing to do with the scalar field. Giving M0 the same datatype (or taking it off the others) keeps each rung to one construct.
M1 does its job on orionbelt. The calculated field comes back as name: amount * 1.1 with amount_with_tax only in obml_column_name and the synonyms: the export writes the field's expression into the OBML column code, and the import takes code as the Ossie field name. I could not find an issue or PR for it, so I will open one. For the grader it is also a hint that elements need an identity beyond their name, otherwise this scores as one DROPPED_SILENT plus one ADDED.
M3 on dbt is the SUM(SUM(CASE WHEN ...)) that #437 is fixing, with the same before and after text as this fixture, so the rung reproduces an open fix rather than a new defect. What it exposes in manifest.yaml is a missing row: the tag is kept and the text changed, which none of the eight outcomes names. Most such rewrites are benign (cube, dbt and omni requalify SUM(amount) to SUM(sales.amount), dbt turns COUNT(sales.order_id) into SUM(CASE WHEN sales.order_id IS NOT NULL THEN 1 ELSE 0 END) the way MetricFlow itself does, sigma and orionbelt quote identifiers, honeydew reorders metrics), so a REWRITTEN outcome only works if the grader compares normalized expressions, say sqlglot trees after qualification and unquoting, and reports the dbt case as a change in meaning rather than in spelling.
The microsoft column needs a row too. The M1 field and the M3 metric go out as BLANK() with the original expression and dialect stored in annotations, with a warning, and the import does not read those annotations back. A DAX dialect is present, so the current vocabulary scores it SURVIVED_VENDOR_ONLY while the content is gone. Either a PLACEHOLDER outcome, or counting it under DROPPED_DIAGNOSED since the export does warn.
Two rows to read with the legend in mind: thoughtspot exits non-zero for the whole document when one element will not translate (M1 is the amount * 1.1 field), so REJECTED there is a document-level outcome, and sigma drops every bare-form metric as cross-dataset on a one-dataset model, same as on the hello-world run.
On the path, and on who produces this table next time. This one came out of the same hand-driven script as the hello-world run, which is fine for calibrating the vocabulary and not fine as the measurement, since nobody else can rerun it. The manifest points scoring at the harness in #348, but that PR has had no review or commit since September 2 and its description is still the template. Unless Isaac is picking it back up, I would put the grader I signed up for next to these fixtures: a thin runner that drives each converter the way converters/cube/tools/interop_matrix.py already does, and a grader that takes the input document and the returned document and emits the per-element outcomes from manifest.yaml, stdlib only, so this table becomes one command. compliance/ on main is a one-line README from the expression language PR and reads as the place for spec compliance tests, while these fixtures measure converters, which are on their way to apache/ossie-converters (#523). So compliance/portability/ is right for now, with the runner beside it, and the whole directory moves with the converters when that lands, unless JB would rather have it wait for the converters repository.
The fixture half of apache#576 (measurements for model portability across converters): a small portable ladder where each rung adds one capability on top of the one below, so a converter round-trip difference localizes to a single construct. M0 baseline (one dataset, one field, one SUM metric, three variants), M1 a scalar calculated-column field, M2 the core aggregate set, M3 a filtered aggregate in the portable SUM(CASE WHEN ...) form. Every fixture is authored in a portable dialect (ANSI_SQL / OSSIE_SQL_2026) so it runs through every converter, and the qualified dataset.field form is carried as primary with the bare form as a sibling variant per apache#486 and apache#343. manifest.yaml lists the fixtures, the element each rung exercises, and the per-element outcome vocabulary a grader assigns. Scoring is left to the interoperability harness in apache#348; conformance stays a floor (all fixtures pass validation/validate.py on current main). Refs apache#576 Co-authored-by: Isaac <no-reply@databricks.com>
…ader, new outcomes) From @kayemkim's nine-converter run on apache#596: - Give the three M0 metrics datatype: Decimal so the metric datatype is constant from M0 and each rung adds exactly one construct (M1 was changing two things and pulling in thoughtspot's datatype warning for an unrelated reason). - Add REWRITTEN (portable tag kept, expression changed) and PLACEHOLDER (a valid stand-in such as BLANK() replaces the content, with a diagnostic) to the outcome vocabulary, the two cases the real run exposed that the eight did not name. - Add the grader the measurement needs under grader/: stdlib diff of input vs returned document into the manifest outcomes, with sqlglot (already a converter and validate.py dependency) used when available to tell a cosmetic REWRITTEN (requalify, unquote, reorder) from one that needs review (e.g. the dbt SUM(SUM(CASE ...)) that apache#437 fixes). Pairs a renamed element by expression so the orionbelt field-renamed-to-its-expression case scores as one changed element, not a drop plus an add. REJECTED is recorded at document scope (thoughtspot). 13 tests, one per outcome plus an identity check grading the real fixtures all-PORTABLE. Refs apache#576 Co-authored-by: Isaac <no-reply@databricks.com>
7d2f764 to
ea88c1e
Compare
|
@kayemkim this is the measurement the fixtures were for, thank you for driving all eight through the nine converters. Sixty-six documents back and every one passing validate.py is the grounding the vocabulary needed, and the two rows that changed meaning are exactly the cases worth naming precisely. I have pushed the changes below to this branch. Fixture fix (the one-construct point). You are right that M0 carrying no metric datatype while M1 up carried one made M1 change two things and pulled in thoughtspot's datatype warning for a reason unrelated to the scalar field. The three M0 metrics now carry Two outcomes the run exposed, now in manifest.yaml.
Element identity. Agreed, and thank you for opening the orionbelt issue. The grader now pairs a dropped input element with an added output element that carries an equivalent expression, so the M1 field coming back with its own expression as its name scores as one element whose identity was not preserved, rather than one DROPPED_SILENT plus one ADDED. Document-level outcomes. The grader records REJECTED at document scope, for the thoughtspot case where the whole document exits non-zero when any one element will not translate. Noted too that sigma drops every bare-form metric as cross-dataset even on a one-dataset model. On who produces the table next time, and the path. Agreed it cannot stay a hand-driven script if it is to be the measurement. I drafted the grader half you describe while this thread was quiet and have pushed it to Agreed |
Summary
The fixture half of #576 (measurements for model portability across converters). A small portable ladder where each rung adds exactly one capability on top of the one below, so that a difference in a converter's round-trip localizes to a single construct.
SUMmetric (three variants)amount * 1.1calculated columnSUM,COUNT,COUNT(DISTINCT),AVG,MIN,MAXSUM(CASE WHEN ... THEN x ELSE 0 END)M0 carries three variants:
ANSI_SQLqualified (primary), the same model taggedOSSIE_SQL_2026to isolate tag survival, and the bare-reference form. This matches the three hello-world variants @kayemkim already drove through the nine converters on the #576 thread, so the baseline rung is a committed version of a run that already exists.Design rules
ANSI_SQLorOSSIE_SQL_2026. A vendor-tagged input would only exercise one converter, which defeats a cross-converter measurement.dataset.fieldform is primary and the bare form is a sibling variant, pending the name-resolution decisions in docs(core-spec): Clarify name resolution for fields, keys, relationships, and metrics #486 and feat: support dataset-scoped metrics #343.manifest.yamllists the fixtures, the element each rung exercises, and the per-element outcome vocabulary.Scope
Rungs M4-M8 (relationships and cross-dataset metrics, metric-to-metric composition, date and time scalars, window and offset functions) are held pending #354, #591 and #587, and are not in this set.
Placement
The files sit under
compliance/portability/as a starting point. If they should live with the interoperability harness from #348 or elsewhere once that lands, they can move: the fixtures are self-contained and the manifest paths are relative. Happy to relocate per reviewer preference.Verification
validation/validate.pyon currentmain(9531429) with sqlglot 29.0.1.Related
Checklist
Compliance
This pull request and its description were written by Isaac.