dengc367 commented on issue #14308:
URL: https://github.com/apache/gravitino/issues/14308#issuecomment-6513509571

   ## Contract update: plan, don't compile
   
   Following the discussion above — and specifically the open question "Should 
the response carry
   SQL text, a structured relational plan, or both?" — I've settled the 
contract for this feature:
   
   **Gravitino resolves a semantic query into a dialect-neutral logical plan; 
the engine materializes
   it. The server never emits SQL.**
   
   Consumers that already own a planner keep owning the dialect matrix, and 
stop re-implementing model
   resolution and join-path logic. This supersedes the SQL-text sketch in the 
proposal above and in
   #14332.
   
   ### Shape
   
   Request: semantic only, no dialect.
   
   ```json
   {
     "metrics": ["Gross_Revenue"],
     "dimensions": ["Region_Name", "Calendar_Month"],
     "filters": [{"field": "Calendar_Month", "operator": "EQ", "value": 
"2026-10"}],
     "limit": 1000
   }
   ```
   
   Response: `{"code": 0, "plan": {...}}` with `sources`, `joins`, 
`selections`, `filters`, `groupBy`,
   `limit`, `warnings`, and the `semanticModelVersion` the plan was resolved 
against. No `sql`, no
   dialect, no aliases, no quoting, no literal syntax.
   
   The constraint that shaped this: Ossie expressions are **per-dialect SQL 
text**
   (`Expression -> DialectExpression[]`), so a fully structured AST would force 
Gravitino to own a SQL
   parser per dialect — a larger liability than the renderer being removed. The 
relational layer is
   fully neutral; the expression layer carries the model's dialect map and lets 
the consumer pick.
   
   Materialization is an SPI: `SemanticQueryPlanConverter<T>` in `api`. It is 
generic so a Trino
   converter can return a `LogicalPlan`, a Spark converter SQL text, and an 
Ossie consumer its own
   nodes.
   
   ### Decisions
   
   | # | Question | Decision |
   | --- | --- | --- |
   | 1 | Version pinning | The plan carries `semanticModelVersion` (drift 
detection; historical-version planning and a `409` mismatch are follow-ups) |
   | 2 | Physical sources | Expose `NameIdentifier` sources, so a JDBC-only 
consumer can render SQL without a Gravitino connection |
   | 3 | `limit` type | `long` |
   | 4 | Filter operators | `EQ/NE/GT/GE/LT/LE` only; `IN`/`LIKE` wait for 
nullability metadata |
   | 5 | Dimension-only queries | Detail rows, no implicit `DISTINCT` |
   | 6 | Naming | `SemanticQueryPlan` and `POST .../plan` |
   | 7 | Converter location | `api` module, so engine plugins don't pull 
`client-java` |
   | 8 | Response envelope | Plan nested under `plan`, leaving room for a 
future optional `materializedSql` |
   
   What this removes from the prototype: `SemanticQuery.dialect`, 
`SemanticQueryPlan.sql`, the
   pluggable planner SPI plus `gravitino.semanticModel.queryPlanner` and its 
`501` path, and the
   in-server Spark renderer, which becomes a reference converter in a library 
module.
   
   ### Prerequisite
   
   The plan carries the version of the definition it was resolved against, but 
`SemanticModel` does
   not expose it today even though the storage layer already versions every 
model. Exposing the
   current committed version on the loaded model is part of the change.
   
   The full contract — API signatures, JSON examples, deterministic resolution 
rules and the error
   matrix — is in [the design 
doc](https://github.com/dengc367/gravitino/blob/dc1397478dee242bae743d5b3c088c1df42eef2c/design-docs/gravitino-semantic-query-plan-contract.md).
   
   I will send the reshaping as a follow-up PR and link it here. Unless there 
are objections, that PR
   will implement this shape.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to