Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions core-spec/spec_layers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Ossie Specification Layers

**Status:** Informational / Architecture Overview (Draft).
**Contributors:** Justin Talbot, Will Pugh, Chris Eubank.

---

## Overview

This document is an informational architecture overview. It describes how the Ossie
specifications fit together and links to the specification for each layer. It does not
define normative requirements itself; those are in each layer's specification.

Ossie is organized into four specification layers, each addressing a distinct concern:

| Layer | Name | Role |
|-------|------|------|
| 1 | Model Definition | Model definition: the Ossie model format and the expression language used within it |
| 2 | Relational Query Interface | Query interface: SQL-native, duplication-free measure evaluation, full SQL invariants |
| 3 | Wide Table Query Interface | Query interface: declarative flat-object queries, heuristic join resolution |
| 4 | Ontology | Ontology workstream: higher-order semantic and knowledge-graph concepts |

Layer 1 defines what an Ossie model *is*—the model format and the expression language authors
use to write it. Layers 2 and 3 are query interfaces that sit on top of a deployed model;
they differ in how much SQL knowledge they require from the consumer. Layer 4 is a separate
workstream covering ontological concepts that SQL does not naturally express.

Each layer can be adopted independently. Layers 2 and 3 compose: the meaning of a wide-table
query (Layer 3) is defined by an equivalent SQL measures query (Layer 2), so correctness
guarantees flow through.

---

## The Layers

### Layer 1 — Model Definition

Layer 1 defines what an Ossie model *is*. It covers two related specifications:

**Model format** ([`spec.md`](spec.md)): the structure of an Ossie model file—datasets,
relationships, fields, and metrics. This is the interchange format: the common schema that
allows semantic model definitions to be moved between tools.

**Expression language** ([`expression_language.md`](expression_language.md)): the portable SQL
expression subset used to write measure definitions, calculated fields, and filter predicates
within a model file. Layer 1 establishes the guarantee: **expressions in an Ossie model
evaluate identically on any conforming engine.** A model authored once can be deployed anywhere
without rewriting its expressions.

Together these define the authoring layer of Ossie. Layer 1 is a model *definition* concern,
not a query concern. It does not prescribe the query language a consumer uses against a deployed
model—that is a per-layer decision for Layers 2 and 3.

Over a single relation, Layer 1 expressions mean what the equivalent SQL expressions mean.
Layer 1 does not define how expressions are evaluated across a model with multiple datasets;
Layers 2 and 3 define that.

### Layer 2 — Relational Query Interface

Layer 2 is the SQL-native query interface for Ossie models. Its query language is the Layer 1
expression language extended with the relational constructs of SQL: joins, group-by, filters,
CTEs, ordering, etc. To this it adds a small set of extensions for measures: a measure column
type, a way to define measures within a query, and the `AGG()` function, which evaluates a
measure.

Layer 2 establishes the guarantee: **measures are evaluated without duplication regardless of

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Layer 3 resolves which source tables to join.
With that, would joining explicitly to other models be a supported scenario in Layer 2? If it is, shouldn't we define the expected semantics for the cases like below

  • A physical table that is part of a model, is joined directly.
  • Two separate models are explicitly joined.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Layer 2 is designed to sit below the Layer 3 multi-table interface. Layer 2 objects behave like tables with measures, while Layer 3 provides a higher-level interface over a graph of datasets. Layer 3 has additional semantics (e.g., dimension domains can depend on which measures are selected) that make interoperability with SQL joins more involved.

To your questions:

  • Joining a physical table: Supported. A regular SQL table can be joined with a Layer 2 dataset, just as it can with any other table.
  • Joining two models: Layer 2 supports explicitly joining datasets from different models. However, joining two Layer 3 model-level query interfaces is outside its scope. Layer 2 operates on datasets and other table-shaped objects, not entire models.

It's reasonable to define how Layer 3 objects, including their graph-aware semantics and dynamic dimension domains, interact with broader SQL. But I'd expect that to be addressed in the Layer 3 proposal rather than Layer 2.

how they are queried.** Fan-out and chasm-trap errors cannot occur when measures are queried
through this interface. The model's datasets are exposed as SQL relations; consumers query them
with ordinary SQL, using `AGG()` in place of raw aggregates.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Shouldn't the BI tools go explicitly through Layer 3? Isn't that simpler, and wouldn't that result in avoiding potentially incorrect queries?

@justint-db justint-db Oct 12, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Generally no. Layer 3 interfaces tend to be very hard for SQL-based BI tools to work with. The reason is that Layer 3 is not relational. So while the results of individual queries against Layer 3 may look reasonable in isolation (and are often completely usable by a human), they do not compose well together.

Perhaps a typical example is a Top N filter, e.g. "Show me the # of unique customers over time in the top 10 states by total revenue".

SQL requires expressing this question as a join between two subqueries that compute the # of unique customers by date and total revenue by state separately. Layer 3 decides which joins to use for those two subqueries independently. If it picks different joins or join types (which is common), Layer 3 does not guarantee that the set of states considered by one subquery align with the set of states considered by the other, so the join of the two subqueries can be incorrect. It could, for example, return no states, even when there are 10 valid states to return.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Experimentally, we've found that BI tools have a much lower barrier to entry connecting to Layer 2 while preserving their existing feature sets.

We've started collecting BI-generated SQL examples in the repository. BI tools generate fairly complex SQL (e.g. subqueries, joins, window functions) and generally assume that the objects they're querying behave like regular tables.

This creates two challenges when connecting directly to Layer 3:

  • SQL compatibility: BI-generated SQL may not run because operations such as joins and COUNT(*) aren't defined over Layer 3 objects.
  • Semantic compatibility: BI tools make assumptions about table-like behavior (e.g. fixed dimension domains) when optimizing queries or implementing features like LoD calculations, Top N filters, and relationships. Those assumptions may not hold for Layer 3 objects, potentially producing incorrect results.

For example, these Tableau experiments illustrate Tableau implementing complex features on top of Layer 2 without product changes, using its existing support for passthrough aggregates.

BI tools also have their own semantics for things like filter propagation and dimension domains in multi-table analyses. Supporting all of these behaviors through Layer 3 would likely require additional extensions and customization.

I agree that Layer 3's higher-level semantics and validity checks are valuable, especially for clients that want the semantic model to handle joins and query construction. But for BI tools that already implement these features, Layer 2 provides a more natural integration point: they can preserve their existing behavior while reusing measures defined in Ossie datasets.

This layer preserves full SQL invariants. Tools that generate SQL, embed SQL in notebooks, or
build on the relational algebra can use Layer 2 without giving up any SQL guarantees.

**Specification:** *(open PR: [apache/ossie#354](https://github.com/apache/ossie/pull/354))*

### Layer 3 — Wide Table Query Interface

Layer 3 is the declarative query interface for Ossie models. It exposes a multi-table model as
a single flat object. The consumer specifies dimensions, measures, and filters; the layer
resolves which source tables to join, in what order, and with what join type. No SQL generation
is required from the consumer.

This interface trades explicit query control for simplicity, making it accessible to ad-hoc
users, AI agents, and BI tools without their own data model. Measure correctness is inherited
from Layer 2: a wide-table query is defined as equivalent to a SQL measures query (with
heuristic join and filter choices), so the same duplication-free evaluation guarantee holds.
Layers 2 and 3 query the same model, so a question that Layer 3 cannot express can be answered
in Layer 2 without changing the model.

**Specification:** *(open PR: [apache/ossie#246](https://github.com/apache/ossie/pull/246))*

### Layer 4 — Ontology

Layer 4 covers higher-order semantic concepts—entities, relationships, and knowledge-graph
constructs that SQL does not naturally represent. It is defined by the Ossie Ontology working
group (`#ossie-ontology-wg`) and is a separate workstream from the query interfaces in Layers
2 and 3.

**Specification:** [`../ontology/ontology.md`](../ontology/ontology.md)

---

## Composition

Layers 2 and 3 compose: the meaning of a wide-table (Layer 3) query is defined by an
equivalent SQL measures (Layer 2) query, with heuristic join and filter choices. This means
correctness guarantees flow from Layer 2 through Layer 3—a consumer using the declarative
interface gets the same duplication-free measure evaluation as one writing SQL directly.

Layer 2 is the semantic target for Layer 3, not a required execution path. An implementation
does not have to translate Layer 3 queries into Layer 2 SQL text; it only has to return the
same results as the equivalent Layer 2 query.

Providers may support one query interface layer or both, at varying compliance levels. The
layered model makes partial adoption coherent: a tool that only needs SQL measures adopts
Layer 2 without taking on the wide-table join semantics of Layer 3.

---

## Background and Prior Work

The layered approach was proposed by Justin Talbot in
[*OSI Layered Query Interface*](https://docs.google.com/document/d/1FOtRNBu6UqA2yeOwUa4jt1r2v45BWQJqS5_BTk34a1c/edit)
(May 2026) and refined by Will Pugh in
[*Proposed Semantics Priorities*](https://docs.google.com/document/d/1EgG5vOlJSubm01S1AGMJ4MKcMcjxBhJHenGKWMr849E/edit)
(August 2026). Will's document introduced the four-layer framing (adding the Ontology layer),
clarified the relationship between the wide-table and SQL-compliant interfaces, and proposed a
prioritization for defining semantics across layers.

The measure model underlying Layer 2 is grounded in Hyde and Fremlin,
[*Measures in SQL*](https://doi.org/10.48550/arXiv.2406.00251) (arXiv:2406.00251).

### Mailing List Discussion

The following `dev@ossie.apache.org` threads trace how the layered model emerged and converged:

- **[Ossie Foundational Semantics](https://lists.apache.org/thread/qo2fx0hl0cvlzn9q1ob9z7v7g81syj88)**
(Will Pugh, July 2026). Will proposed a foundational semantics spec (PR #246) covering the
wide-table query interface and asked the community for feedback and a path to a reference
implementation.

- **[[DISCUSS] PRs #246 (Foundational Semantics) and #237 (Compliance Suite)](https://lists.apache.org/thread/mqlbbb4ndhb0qo9sf2yn60fb9tlzv59t)**
(Justin Talbot and Chris Eubank, August 2026). Raised concerns that PR #246 bundled normative
correctness guarantees (duplication-free aggregation) with opinionated choices (join paths, filter
propagation, join types) in a way that made adoption all-or-nothing for BI vendors. Argued for
separating the two into distinct layers.

- **[[DISCUSS] SQL with measures as the Ossie BI / semantic layer interface](https://lists.apache.org/thread/0td2v8n2llqxyqw0r6w51fkt8klp8x5w)**
(Chris Eubank, August 2026) and
**[[DISCUSS] Ossie BI / semantic layer interface based on SQL with measures](https://lists.apache.org/thread/q95or2395khvs21nzmwkmwy1vpdgjy87)**
(Justin Talbot, August 2026). Proposed SQL with measures (the *Measures in SQL* model) as a
lower, SQL-native layer beneath the wide-table interface, giving SQL-fluent BI tools a path to
adopt Ossie without taking on multi-table join semantics.

- **[[DISCUSS] Relational Query Interface spec (core-spec)](https://lists.apache.org/thread/b3nty67729wm5vc3ylnp8phgtxl90n4t)**
(Justin Talbot, September 2026). Announced PR #354, the Layer 2 specification.

- **[[DISCUSS] Landing Ossie semantics and compliance suites](https://lists.apache.org/thread/1jhvnw8vg5fgtct347t62ycc2zkrox6l)**
(Chris Eubank, September 2026). Summarized the convergence: working-group discussion settled on
the hybrid layered model, with Layer 3 (PR #246) and Layer 2 (PR #354) as separate specs both
building on Layer 1, and Layer 3's output expressible in terms of Layer 2 primitives.
Loading