Skip to content

Support Omni relationships file, topics, and richer field metadata#205

Open
nicosuave wants to merge 3 commits into
mainfrom
update-omni-adapter
Open

Support Omni relationships file, topics, and richer field metadata#205
nicosuave wants to merge 3 commits into
mainfrom
update-omni-adapter

Conversation

@nicosuave

Copy link
Copy Markdown
Member

What changed

The Omni import adapter (sidemantic/adapters/omni.py) targeted a pre-"relationships-file" era of Omni. Running it on a current real export (tests/fixtures/omni/estore, sourced from vbalalian/estore-analytics, MIT) produced 6 models but 0 relationships and 0 topics. This brings the adapter up to date with the current Omni export format.

Parsing

  • Global relationships file: parse relationships.yaml/.yml as a bare top-level list of joins (current Omni), in addition to the existing nested relationships: key inside model.yaml (older exports).
  • Topics: read *.topic.yaml files. Each topic's base_view, label, description, and flattened joined_views are recorded on graph.topics, and its nested joins are realized as relationships from each parent view to its joined views.
  • View discovery and naming: discover *.view.yaml files and name each view by Omni's reference convention {schema}__{table_name} (e.g. omni_dbt_marts__dim_users) when no explicit name: is present, so relationships and topic joins resolve against the correct model keys. An explicit name: still wins.

Fields

  • Add assumed_many_to_one relationship type (maps to many_to_one, flagged in metadata).
  • Map extended aggregate types: median, median_distinct_on, sum_distinct_on, average_distinct_on to the closest Sidemantic aggregation; percentile and list parse as custom-SQL measures with the original aggregate_type preserved in metadata.
  • Support filter operators beyond is/greater_than_or_equal_to: not, greater_than, less_than, less_than_or_equal_to, contains, starts_with, ends_with, between, with type-aware value quoting (numbers/booleans unquoted).
  • Preserve dimension/measure metadata: format, synonyms, all_values, sample_values, suggestion_list, bin_boundaries, order_by_field, timeframes.
  • Support multiple timeframes per time dimension: the first sets the base granularity, the full list becomes supported_granularities.

Field names verified against docs.omni.co.

Backward compatibility

The old nested-format fixture (tests/fixtures/omni/model.yaml) and all prior dimension/measure/relationship/roundtrip behavior remain supported and green.

Tests

  • tests/adapters/omni/test_estore.py updated to the canonical view names, with new assertions for the relationships file, topics (base view, labels, nested-join flattening), and dimension/measure metadata.
  • tests/adapters/omni/test_parsing.py adds coverage for extended aggregate types, all new filter operators, multiple timeframes, a bare global relationships file (including assumed_many_to_one), and topic-to-relationship realization.
  • Two fixture-coverage contract tests updated to reflect that standalone topic files yield an empty graph and that *.view.yaml files now compile (named without a . in the model name).

Known limitations

  • Topics are exposed via graph.topics and as realized relationships; there is no first-class Topic model in the core graph.
  • percentile/list aggregations have no native Sidemantic equivalent, so they are carried as custom-SQL/metadata rather than a typed aggregation.

…data

The Omni adapter targeted a pre-"relationships-file" era: running it on a
current real export (tests/fixtures/omni/estore) produced 6 models but 0
relationships and 0 topics.

Parsing:
- Read a global relationships.yaml/.yml as a bare top-level list of joins
  (current Omni), alongside the existing nested relationships: key in model.yaml.
- Read topic files (*.topic.yaml): record base_view/label/joins on graph.topics
  and realize their nested joins as relationships.
- Discover views as *.view.yaml (Omni's filename convention) and name them by
  Omni's {schema}__{table_name} reference convention so joins and topics resolve.

Fields:
- Add assumed_many_to_one (maps to many_to_one, flagged in metadata).
- Map extended aggregate types: median, median_distinct_on, sum_distinct_on,
  average_distinct_on (to the closest Sidemantic aggregation); percentile and
  list parse as custom-SQL measures with the original type kept in metadata.
- Support filter operators beyond is/greater_than_or_equal_to (not, greater_than,
  less_than(_or_equal_to), contains, starts_with, ends_with, between) with
  type-aware value quoting.
- Preserve dimension/measure metadata: format, synonyms, all_values,
  sample_values, suggestion_list, bin_boundaries, order_by_field, timeframes.
- Support multiple timeframes per time dimension (first sets base granularity,
  full list becomes supported_granularities).

The old nested-format fixture (tests/fixtures/omni/model.yaml) and all prior
behavior remain supported.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eea843e791

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sidemantic/adapters/omni.py Outdated
The Omni relationship parser extracted on_sql keys positionally: the
from_view column always became foreign_key and the to_view column always
became primary_key. That is correct for many_to_one, but Sidemantic
interprets primary_key as the local key and foreign_key as the related
key for one_to_many/one_to_one, so e.g. customers one_to_many orders on
${customers.id} = ${orders.customer_id} compiled to the reversed,
invalid join customers.customer_id = orders.id.

Make _keys_from_on_sql cardinality-aware and mirror the same direction
logic in _export_relationships so import/export round-trips stay
consistent. Add regression tests covering key extraction, the compiled
join condition, and export round-trip with distinct key names on each
side.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6678eec45

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sidemantic/adapters/omni.py Outdated
Comment thread sidemantic/adapters/omni.py Outdated
Do not map sum_distinct_on/average_distinct_on/median_distinct_on to a plain
sum/avg/median: those collapse the per-key dedup and overcount on fan-out.
Leave agg unset so they parse as custom measures with the original aggregate_type
and custom_primary_key_sql preserved in metadata.

Name schema-less views by their file stem instead of table_name so relationships
and topics that reference the view name attach instead of being dropped when
table_name differs from the file name.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant