Repository navigation
fix(converters): emit schema-conformant OSI documents (drop non-spec root dialects/vendors) - #148
andreybavt wants to merge 1 commit into
Conversation
Drop the non-spec root `dialects`/`vendors` fields from OSIDocument and stop the dbt converter emitting a root dialect, so dbt->OSI output validates against core-spec/osi-schema.json. Dialects remain per-expression (no information lost). Add a regression test that schema-validates converter output.
|
@khush-bhatia , let me know if this first PR follows the community guidelines. Happy to take bigger scope after this first one lands |
khush-bhatia
left a comment
There was a problem hiding this comment.
Thanks for the fix.
QMalcolm
left a comment
There was a problem hiding this comment.
Looks good to me! Thank you for putting this together 🙂
|
Thanks @andreybavt, We will merge this PR soon, we are waiting on some process to complete. |
|
Thanks @khush-bhatia and @QMalcolm ! Will continue with the other PRs then |
…a-conformant OSI Addresses review feedback on this PR. The converter only emitted ANSI_SQL on the OBML -> OSI path, so a third-party OSI model (Snowflake/Databricks authored, or a non-SQL dialect) could lose metrics on import with only a warning, contradicting the README's lossless roundtrip claim. - Dialect catching: read ANSI_SQL, then SNOWFLAKE, then DATABRICKS expressions (SQL engines whose aggregations are ANSI-compatible); MDX/TABLEAU/MAQL are not parsed as SQL. - No silent loss: metrics with no OBML representation are preserved verbatim under an OSI-vendor model-level customExtension (obml_unconverted_metrics) and re-emitted on OBML -> OSI, with a loud LOSSY: warning. OSI -> OBML -> OSI stays lossless. - Schema conformance (aligns with PR apache#148): stop emitting root-level dialects/vendors. The published OSI core schema's root is additionalProperties:false (version + semantic_model only). Dialects live per-expression in expression.dialects[] and vendors per-entity in custom_extensions, the schema-valid homes, so no information is lost. Vendored schema updated to match published; a guard test asserts the root arrays are now rejected. - Name-collision safety: a preserved metric whose name a converted metric now owns is skipped on export, so the output has no duplicate metric names. - Idempotency: convert() resets per-run accumulators on both directions. - Docs: scope the README fidelity claim; refresh stale v0.1.1 references and the primary_key entry in the mapping analysis. - Tests: foreign-OSI fixtures covering both former drop paths, schema conformance, name collision, and idempotency.
…a-conformant OSI
Addresses review feedback on this PR. The converter only emitted ANSI_SQL on the
OBML -> OSI path, so a third-party OSI model (Snowflake/Databricks authored, or a
non-SQL dialect) could lose metrics on import with only a warning, contradicting
the README's lossless roundtrip claim.
- Dialect catching: read ANSI_SQL, then SNOWFLAKE, then DATABRICKS expressions
(SQL engines whose aggregations are ANSI-compatible); MDX/TABLEAU/MAQL are not
parsed as SQL.
- Identifier resolution: parsed dataset.column references are resolved against
the OSI dataset/field map case-insensitively and with SQL quoting stripped, so
Snowflake forms like SUM(ORDERS.AMOUNT) or SUM("Orders"."amount") map to the
real Orders.amount. Unmappable references preserve the metric verbatim instead
of emitting a dangling reference.
- No silent loss: metrics with no OBML representation are preserved verbatim
under an OSI-vendor model-level customExtension (obml_unconverted_metrics) and
re-emitted on OBML -> OSI, with a loud LOSSY: warning. OSI -> OBML -> OSI stays
lossless.
- Schema conformance (aligns with PR apache#148): stop emitting root-level
dialects/vendors. The published OSI core schema's root is
additionalProperties:false (version + semantic_model only). Dialects live
per-expression in expression.dialects[] and vendors per-entity in
custom_extensions, the schema-valid homes, so no information is lost. Vendored
schema updated to match published; a guard test asserts the root arrays are
now rejected.
- Name-collision safety: a preserved metric whose name a converted metric now
owns is skipped on export, so the output has no duplicate metric names.
- Idempotency: convert() resets per-run accumulators on both directions.
- Docs: scope the README fidelity claim; refresh stale v0.1.1 references and the
primary_key entry in the mapping analysis.
- Tests: foreign-OSI fixtures covering both former drop paths, identifier
resolution, schema conformance, name collision, and idempotency.
|
@andreybavt Because of the rename, there are some merge conflicts, could you please resolve the conflicts. |
|
Closing due to changes in the core spec + move of converters to ossie-converters. @andreybavt if you're interested, there are a number of new issues to solve in ossie and the ossie-converters repo |
Problem
Output from the dbt→OSI converter fails OSI's own validator (
validation/validate.py)against the published core schema:
Because the CLI writes via
to_osi_yaml(), everydbt→OSIconversion produces anon-conformant document.
Root cause
OSIDocument(python/src/osi/models.py) declared optional root-leveldialects/vendorsfields that aren't incore-spec/osi-schema.json, whose root isadditionalProperties: false(onlyversion+semantic_model). The dbt converterset
dialects=[self._dialect], sodialectswas emitted at the document root.Fix
dialects/vendorsfields fromOSIDocument.Per-expression dialect tagging (
OSIExpression.dialects) is unchanged and remains theschema-valid home for dialects, so no information is lost. Dialect selection still
flows end-to-end; the two affected converter tests now assert it on the per-expression path.
Regression guard
Adds
converters/dbt/tests/test_schema_conformance.py, which converts a representativemanifest and validates the emitted document (YAML and JSON, for
ANSI_SQLandSNOWFLAKE) againstcore-spec/osi-schema.json, reusingvalidation/validate.py.CI now fails if a converter emits a non-conformant document root again.
Testing
validate.pyon converter output: fails before ('dialects' was unexpected),passes after.
Out of scope
Whether OSI should support a document-level (default) dialect is the open discussion in
#52 (one dialect per document) and #16 (default dialect at dataset level). This PR takes
no position and makes no schema change - it only aligns the reference model and
converter with the schema as published today.