Skip to content

Releases: boringdata/boring-semantic-layer

v0.3.14

20 May 05:16
f864ff5

Choose a tag to compare

boring-semantic-layer v0.3.14

Highlights

This release fixes joins on plain ibis backends (Snowflake, Databricks, BigQuery), unifies calc-measure compilation on an ibis-native classifier (ADR 0001), and includes several correctness fixes around joins and serialization.

  • Fixed ValueError: Don't know how to handle type <class 'ibis.expr.types.relations.Table'> when joining models on Snowflake / Databricks / BigQuery (#222, fixes #221)
  • Unified calc measures on the new ibis-native classifier (#262, ADR 0001 phases 1+2)
  • Fixed grain mismatch when chaining with_measures over joined models (#261)
  • Fixed serialization content hashing to include BSL metadata (#264)

Why upgrade

  • If you're on Snowflake, Databricks, BigQuery, or any other backend xorq doesn't wrap, joined-model queries now execute natively instead of crashing
  • The new calc-measure compiler is faster, surfaces clearer errors on type-inference failures, and correctly preserves user casts
  • Catalog workflows relying on tag content hashes will now invalidate correctly when BSL metadata changes

Included changes

Fixes

  • #222 — handle plain ibis backends in join backend rebinding (fixes #221)
  • #261 — preserve preagg + canonical backend through with_measures on joins
  • #264 — use HashingTag so BSL metadata contributes to content hash

Features / refactors

  • #262 — unify calc measures on ibis-native classifier (ADR 0001 phases 1+2)
    • New calc_analyzer and calc_compiler modules
    • Inline-reduction lift and runtime orchestration
    • Windowed totals carried through aggregation (replaces cross-join totals)
    • Tighter bare-ref detection, surfaced lift failures, asserted totals substitutions

Upgrade

pip install --upgrade boring-semantic-layer==0.3.14

v0.3.13

05 May 11:10

Choose a tag to compare

boring-semantic-layer v0.3.13

Highlights

This release adds metadata support on model fields, expands xorq/TagHandler integration, improves MCP tooling, and fixes several round-trip and serialization correctness issues.

  • Added metadata field on Dimension and Measure for arbitrary annotations (#245, #246)
  • Exposed BSL TagHandler via xorq.from_tag_node entry point for catalog workflows (#235)
  • Added reemit support on TagHandler for full catalog rebuild (#244)
  • Added MCP period comparison workflow (#238)
  • Fixed join rebind guard for non-xorq backends (#242, #243)
  • Fixed multiple round-trip and serialization correctness issues in xorq boundary and calc-measure handling

Why upgrade

  • If you use metadata on dimensions or measures, this is the release that adds it
  • If you're integrating BSL with xorq catalog workflows, the new TagHandler entry points make that cleaner
  • Several xorq serialization round-trip bugs are fixed — recommended if you serialize/deserialize semantic models

Included changes

Features

  • #238 — MCP period comparison workflow
  • #244 — TagHandler reemit for catalog rebuild
  • #245/#246metadata field on Dimension and Measure
  • #235 — expose BSL TagHandler via xorq.from_tag_node

Fixes

  • #242/#243 — guard join rebind against non-xorq backends
  • Fix: walk join branches in tag_handler.extract_metadata
  • Fix: roundtrip model-level description through to_tagged/from_tagged
  • Fix: preserve join cardinality on round-trip; fix pre-agg grain for derived dims
  • Fix: treat UnboundTable as leaf node in _reconstruct_table
  • Fix: use matching ibis module for desc() in MCP search_dimension_values
  • Fix: broaden agg-method recognition, surface typos, pin ibis workaround

Refactors

  • Introduce Predicate AST for filter expressions
  • Tighten calc-measure AST and surface type-inference failures
  • Route all xorq imports through single _xorq shim
  • Convert ibis→xorq once at SemanticModel construction
  • Dispatch reduction-type check on expr's ibis flavor

Install

pip install -U boring-semantic-layer==0.3.13

v0.3.12

15 Apr 18:22

Choose a tag to compare

boring-semantic-layer v0.3.12

Highlights

This release focuses on join planning and reliability.

  • Added deferred join_one support for dimension lookups after aggregation (#220)
  • Added grain-aware join_one behavior via is_entity dimensions (#219)
  • Pruned unused dimension joins from generated queries for leaner SQL (#228)
  • Fixed demo_bsl_v2.py so the example script works again (#236)
  • Added regression coverage for read-only DuckDB joined dimension introspection (#237, refs #232)

Why upgrade

If you use joined semantic models, this release improves correctness and efficiency:

  • better handling of dimension lookups across joins
  • better join behavior when entity grain is defined explicitly
  • fewer unnecessary joins in compiled queries
  • better protection against regressions around read-only DuckDB joined introspection (#232)

Included changes

  • #219 — grain-aware join_one via is_entity dimensions
  • #220 — deferred join_one for dimension lookups after aggregation
  • #228 — prune unused dimension joins from generated queries
  • #232 — regression coverage for read-only DuckDB joined introspection
  • #236 — repair demo_bsl_v2.py
  • #237 — add regression test coverage for read-only joined dimensions

Install

pip install -U boring-semantic-layer==0.3.12

v0.3.11

02 Apr 04:33

Choose a tag to compare

What's Changed

  • fix: route dimension-only queries to source table on joins (#225)
    • Dimension-only queries (no measures) on joined models now route directly to the source dimension table
    • Ensures dimension members with no matching fact rows are still returned
    • Supports filters on the target dimension table
    • Falls back to standard join path when filters reference other tables

Full Changelog: v0.3.10...v0.3.11

v0.3.10

25 Mar 18:59

Choose a tag to compare

What's New

Features

  • HTTP server transport — Optional bsl serve command exposes BSL models over REST via FastAPI (pip install boring-semantic-layer[server]) (#214)
  • Per-dimension time grainstime_grains parameter lets each time dimension use a different grain (e.g., {"order_date": "month", "ship_date": "quarter"}) (#214)
  • Short grain names — Core query() now accepts "month", "quarter", etc. alongside "TIME_GRAIN_MONTH" (#214)
  • Derived time dimensions — Auto-generate year/month/day parts from time dimensions via derived_dimensions (#215, closes #213)
  • Plain ibis backend support — BSL works with any ibis backend (Databricks, ClickHouse, MySQL, etc.) without xorq wrapping (#217)
  • Self-joins with aliases — Join the same model multiple times in YAML with different aliases (#205, addresses #114)
  • YAML calculated_measures — Support calculated_measures and .all() in YAML definitions (#211)

Fixes

  • Fix content hashing so models with different measures/dimensions produce different hashes (#209)
  • Fix 15 broken links across documentation (#208)
  • Fix model prefix behavior in with_dimensions/with_measures after joins (#211)

Internal

  • Convert to_untagged() to return xorq-vendored ibis types consistently (#203)

v0.3.9

09 Mar 12:45

Choose a tag to compare

What's Changed

Features

  • Measure filtering: Support filtering by measures in query() (#178)
  • MCP tool: Add search_dimension_values MCP tool for discovering dimension values

Refactoring

  • Serialization: Move serialization into dedicated package with singledispatch architecture
  • xorq vendored types: Convert to_untagged() to return xorq-vendored ibis types at the leaf (#203)
  • Eliminate cloudpickle: Remove cloudpickle from xorq tag serialization (v2.0)
  • Deduplicate: Consolidate deserialization, join deprecation, and xorq unwrapping

Bug Fixes

  • Preserve mutated group-by columns in join_many pre-aggregation (#187)
  • Add join methods to SemanticFilter for from_config compatibility (#186)
  • Support multi-level derived dimensions in filters (#182)
  • Strip VARCHAR(N) length from dtype strings in _make_schema (#183)
  • Make join_one use left outer join by default (Malloy semantics)
  • Preserve unmatched left-join rows in pre-aggregation
  • Resolve ambiguous field reference in multi-way joins with shared column names
  • Propagate is_right_of_many through nested joins in pre-aggregation
  • Compute actual ibis join depth for column rename suffix
  • Resolve unprefixed measure names via suffix matching on joined models
  • Split join expression in from_tagged to prevent cross-join on round-trip

Performance

  • Compute COUNT DISTINCT on raw source table when possible

Full Changelog: v0.3.8...v0.3.9

v0.3.8

24 Feb 20:45
ce42e6f

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.3.7...v0.3.8

v0.3.7

27 Jan 12:18

Choose a tag to compare

What's Changed

  • feat: add CSS theming support via YAML frontmatter (#157)

Full Changelog: v0.3.6...v0.3.7

v0.3.6

26 Jan 13:13
93e25ba

Choose a tag to compare

What's Changed

  • ECharts chart backend - New visualization backend with bar, line, pie, scatter, area charts and auto chart detection
  • Dashboard renderer - 16-column CSS grid layout for markdown-based dashboards
  • Altair remains default - ECharts available via backend="echarts"

Full Changelog: v0.3.5...v0.3.6

v0.3.5

22 Jan 10:30

Choose a tag to compare

What's Changed

  • fix: resolve time_grain infinite recursion with Deferred expressions by @benjaminsicard in #152
    • Fix infinite recursion when using time_grain with Deferred dimension expressions
    • Fix timestamp comparison errors when using time_range with certain database backends
    • Use Dimension.__call__ for time_range filters (properly resolves Deferred)
    • Add regression tests for Deferred expressions with time_grain and time_range

Full Changelog: v0.3.4...v0.3.5