Skip to content

[#12210] docs: Add Semantic Model design - #12424

Open
mchades wants to merge 1 commit into
apache:mainfrom
mchades:semantic-model-design
Open

[#12210] docs: Add Semantic Model design#12424
mchades wants to merge 1 commit into
apache:mainfrom
mchades:semantic-model-design

Conversation

@mchades

@mchades mchades commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Add a design document that models an Ossie-compatible SemanticModel as an independent,
first-class, schema-scoped metadata object in Gravitino. The document defines its object model,
validation, APIs, lifecycle, persistence, governance, connector behavior, UI support, and
development plan.

Why are the changes needed?

Semantic definitions describe datasets, fields, relationships, and metrics that consumers combine
at query time. They are not inherently relational Views with fixed query logic and output schemas.
A dedicated metadata object provides clear identity, lifecycle, and governance without overloading
View semantics.

Fix: #12210

Does this PR introduce any user-facing change?

No. This is a design-document-only change; the proposed APIs and behavior are not implemented yet.

How was this patch tested?

Not applicable. This is a design-document-only change.

@github-actions

Copy link
Copy Markdown

Code Coverage Report

Overall Project 68.4% 🟢
Files changed No Java source files changed -

Module Coverage
aliyun 1.72% 🔴
api 49.31% 🟢
authorization-common 85.96% 🟢
aws 42.04% 🟢
azure 2.47% 🔴
catalog-common 9.92% 🔴
catalog-fileset 79.77% 🟢
catalog-glue 68.95% 🟢
catalog-hive 79.4% 🟢
catalog-jdbc-common 45.7% 🟢
catalog-jdbc-doris 81.8% 🟢
catalog-jdbc-mysql 79.33% 🟢
catalog-jdbc-postgresql 83.39% 🟢
catalog-jdbc-starrocks 79.16% 🟢
catalog-kafka 77.01% 🟢
catalog-lakehouse-generic 59.18% 🟢
catalog-lakehouse-hudi 79.1% 🟢
catalog-lakehouse-iceberg 85.93% 🟢
catalog-lakehouse-paimon 84.23% 🟢
catalog-model 77.72% 🟢
cli 44.48% 🟢
client-java 78.28% 🟢
common 52.77% 🟢
core 83.33% 🟢
filesystem-hadoop3 77.28% 🟢
flink 0.0% 🔴
flink-common 48.68% 🟢
flink-runtime 0.0% 🔴
gcp 14.12% 🔴
hadoop-auth 68.0% 🟢
hadoop-common 12.7% 🔴
hive-metastore-common 53.4% 🟢
iceberg-aliyun-bundle 0.0% 🔴
iceberg-common 64.75% 🟢
iceberg-rest-server 75.1% 🟢
idp-basic 86.02% 🟢
integration-test-common 0.0% 🔴
jobs 62.92% 🟢
lance-common 31.75% 🔴
lance-rest-server 63.47% 🟢
lineage 53.02% 🟢
optimizer 83.24% 🟢
optimizer-api 21.95% 🔴
server 85.76% 🟢
server-common 76.69% 🟢
spark 28.57% 🔴
spark-common 45.89% 🟢
tencent 69.84% 🟢
trino-connector 40.29% 🟢

@laserninja laserninja left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Checked the contract against the pinned Ossie schema at 88e0011: field names, required/optional markers, cardinalities, and the Dialect/DataType enums all match. Making this a first-class entity also resolves the View-namespace and per-entity-version concerns from the earlier design. Six points below, mostly where the Gravitino side of the contract is still unspecified.

Two nits: the Java example writes DataType.DECIMAL while the wire value is Decimal, and it'd help to say whether DataType relates to org.apache.gravitino.rel.types.Type or deliberately doesn't. Also REST create inlines datasets/relationships/metrics at top level while replaceDefinition nests them under definition - Java uses SemanticModelDefinition for both.

vendor_name: string
data: string

Dialect = "ANSI_SQL" | "SNOWFLAKE" | "MDX" | "TABLEAU"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

None of Gravitino's own engine dialects appear here. Dialects (api/src/main/java/org/apache/gravitino/rel/Dialects.java:31-40) defines trino, spark, hive, flink and explicitly allows unlisted strings; this enum is closed and has none of them. Worth stating what a user with a Trino- or Spark-specific metric expression does - ANSI_SQL looks like the only option - and whether Gravitino would ever accept a dialect outside the enum, since that breaks the conformance claim below.

caller cannot access.

Invalid definitions return `400`. Missing sources or source columns are invalid definitions. A
temporarily unavailable source catalog returns `503` so the caller can retry. Authorization failures

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Gravitino has no 503 in its error model. ErrorConstants has no service-unavailable code, and an unreachable underlying catalog already maps to 502 via Utils.connectionFailed (server-common/src/main/java/org/apache/gravitino/server/web/Utils.java:85) with CONNECTION_FAILED_CODE = 1007, which the Java client switches on in ErrorHandlers. Either reuse connection-failed or note that a new code plus client handling is part of this work.

Dimension
is_time?: boolean

AIContext = string | AIContextObject

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The typed API shape for this union isn't specified - the Java example never constructs an AIContext. The schema sets additionalProperties: true on the object form and the doc promises lossless retention, so it'd help to say whether this is a sealed type with string and object variants and where the unknown properties live (e.g. Map<String, Object>), since that also determines equality and JSON round-tripping.

- Create writes the identity row and version 1 snapshot in one transaction.
- Alter writes a complete new snapshot, increments `last_version`, and advances `current_version` in
the same transaction. Rename also updates `semantic_model_meta.semantic_model_name`; the version
snapshot retains the name at the time of the change.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing here prevents a lost update: two concurrent replaceDefinition calls each validate against the state they read, and the second silently overwrites the first with no way for the caller to detect it. Worth stating the intent - last-write-wins, or an optimistic check against current_version. ErrorConstants.OPTIMISTIC_LOCK_CONFLICT_CODE (1012) already exists if you want the latter.

```

The projection maps the entity name to `SemanticModel.name`, `comment` to `description`, and each
source `NameIdentifier` to its three-part string. The request path supplies the metalake and is not

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The three-part string is ambiguous in both directions. NameIdentifier.parse splits on . with no quoting or escaping (api/src/main/java/org/apache/gravitino/NameIdentifier.java:36), so a catalog, schema, or table name containing a dot can't be parsed back from an imported Ossie source, and export produces a string that doesn't round-trip. Worth stating the escaping rule, or that such names are rejected at write time.


### API and Lifecycle

`Catalog` exposes `asSemanticModelCatalog()`. Because definitions are stored by Gravitino, support

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Which Catalog.Type values support this? The sibling asTableCatalog/asViewCatalog accessors (api/src/main/java/org/apache/gravitino/Catalog.java:214-254) throw UnsupportedOperationException per catalog type, and "every catalog that supports schemas" in the Connector section would include FILESET, MESSAGING, and MODEL catalogs, whose schemas contain no Tables or Views to reference. If the intent is RELATIONAL only, say so.

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.

Only supports the relational catalog.

KEY `idx_smvi_sid` (`schema_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
COMMENT 'semantic model version information';
```

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.

We should support OCC mechanism for CRUD like what @yuqi1129 did for now, just FYI.

| Privilege | Purpose |
| ------------------------- | ------------------------------------------------- |
| `CREATE_SEMANTIC_MODEL` | Create a Semantic Model under a schema |
| `USE_SEMANTIC_MODEL` | Discover and load the model definition |

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.

Shall we align with the table definition like "SELECT_SEMANTIC_MODEL"?

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.

[Subtask] Design Semantic Model support in Gravitino

3 participants