jerryshao commented on code in PR #12627: URL: https://github.com/apache/gravitino/pull/12627#discussion_r4236207243
########## docs/open-api/semantic-models.yaml: ########## @@ -0,0 +1,1588 @@ +# 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. + +--- + +paths: + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + get: + tags: + - semantic-model + summary: List Semantic Models + description: >- + Lists the Semantic Models in a schema. Semantic Models are supported only for relational + catalogs. Each returned identifier uses the full metalake.catalog.schema.name namespace. + operationId: listSemanticModels + responses: + "200": + $ref: "#/components/responses/SemanticModelListResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" Review Comment: [Important] All seven operations document `405` for a non-relational catalog, but the server returns `501 Not Implemented`. `SemanticModelExceptionHandler` routes `UnsupportedOperationException` to `Utils.unsupportedOperation` (`ExceptionHandlers.java:1036-1037`), which builds `Response.status(Response.Status.NOT_IMPLEMENTED)` (`server-common/src/main/java/org/apache/gravitino/server/web/Utils.java:213-218`). `TestSemanticModelOperations.java:413-425` throws `new UnsupportedOperationException("catalog is not relational")` and asserts `Response.Status.NOT_IMPLEMENTED` with `UNSUPPORTED_OPERATION_CODE`. The sibling spec documents the identical situation as 501: `docs/open-api/statistics.yaml:55` - "Not Implemented - Statistics are not supported for the specified object". This file is the only one under `docs/open-api/` that uses `405` at all. Please change `"405"` to `"501"` at lines 45, 77, 137, 172, 205, 240 and 284, and reword the shared response at line 1212-1213 from `Method Not Allowed - ...` to `Not Implemented - ...` (the component name is fine as is; only the status and the description are wrong). Worth fixing rather than leaving: 405 is also what a servlet container returns for a wrong HTTP method, so a client that branches on it will mis-handle a non-relational catalog as a routing bug. Verified by: reading ExceptionHandlers.java:1024-1048, Utils.java:202-218, TestSemanticModelOperations.java:413-425, and comparing with statistics.yaml:40-62 on this branch. ########## docs/open-api/semantic-models.yaml: ########## @@ -0,0 +1,1588 @@ +# 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. + +--- + +paths: + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + get: + tags: + - semantic-model + summary: List Semantic Models + description: >- + Lists the Semantic Models in a schema. Semantic Models are supported only for relational + catalogs. Each returned identifier uses the full metalake.catalog.schema.name namespace. + operationId: listSemanticModels + responses: + "200": + $ref: "#/components/responses/SemanticModelListResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + post: + tags: + - semantic-model + summary: Create a Semantic Model + description: >- + Creates a schema-scoped Semantic Model in a relational catalog. The complete definition is + validated before the model is stored, including source identifier shape. Source existence, + source columns, and source authorization checks are not yet implemented. + operationId: createSemanticModel + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SemanticModelCreateRequest" + examples: + SemanticModelCreateRequest: + $ref: "#/components/examples/SemanticModelCreateRequest" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlreadyExistsResponse" + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/ossie: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + post: + tags: + - semantic-model + summary: Import an Apache Ossie Semantic Model + description: >- + Imports one standalone Apache Ossie document and creates the represented Semantic Model. + The request body is the raw JSON or YAML document, not a JSON-encoded string. Content-Type + selects the parser, and parsing does not fall back to another format. + operationId: importOssieDocument + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + application/yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + application/x-yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + text/yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlreadyExistsResponse" + "415": + description: >- + Unsupported Media Type - Content-Type must be application/json, application/yaml, + application/x-yaml, or text/yaml Review Comment: [Question] This text says Content-Type must be one of the four listed media types, which matches `@Consumes({APPLICATION_JSON, application/yaml, application/x-yaml, text/yaml})` on `importOssieDocument`. But that method's own Javadoc states the opposite for the absent case: "The `Content-Type` header selects the document format; an absent header defaults to YAML" (`server/src/main/java/org/apache/gravitino/server/web/rest/SemanticModelOperations.java:171`). Under JAX-RS a request with no Content-Type is matched as `application/octet-stream`, which none of the four `@Consumes` values accepts, so I would expect 415 rather than a YAML default - and no test settles it (`TestSemanticModelOperations.java:775-781` only covers `text/plain` -> 415). Which is the intended contract? If 415 is correct, the Javadoc is stale; if the YAML default is correct, this 415 description should say the header is optional. Either way one sentence here would stop clients that omit the header from guessing. Verified by: reading SemanticModelOperations.java:169-186 (@Consumes and Javadoc) and the import tests in TestSemanticModelOperations.java:761-796; no test exercises a missing Content-Type. ########## docs/open-api/semantic-models.yaml: ########## @@ -0,0 +1,1588 @@ +# 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. + +--- + +paths: + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + get: + tags: + - semantic-model + summary: List Semantic Models + description: >- + Lists the Semantic Models in a schema. Semantic Models are supported only for relational + catalogs. Each returned identifier uses the full metalake.catalog.schema.name namespace. + operationId: listSemanticModels + responses: + "200": + $ref: "#/components/responses/SemanticModelListResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + post: + tags: + - semantic-model + summary: Create a Semantic Model + description: >- + Creates a schema-scoped Semantic Model in a relational catalog. The complete definition is + validated before the model is stored, including source identifier shape. Source existence, + source columns, and source authorization checks are not yet implemented. + operationId: createSemanticModel + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SemanticModelCreateRequest" + examples: + SemanticModelCreateRequest: + $ref: "#/components/examples/SemanticModelCreateRequest" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlreadyExistsResponse" + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/ossie: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + post: + tags: + - semantic-model + summary: Import an Apache Ossie Semantic Model + description: >- + Imports one standalone Apache Ossie document and creates the represented Semantic Model. + The request body is the raw JSON or YAML document, not a JSON-encoded string. Content-Type + selects the parser, and parsing does not fall back to another format. + operationId: importOssieDocument + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + application/yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + application/x-yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + text/yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlreadyExistsResponse" + "415": + description: >- + Unsupported Media Type - Content-Type must be application/json, application/yaml, + application/x-yaml, or text/yaml + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/{semanticModel}: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + - $ref: "./openapi.yaml#/components/parameters/semanticModel" + + get: + tags: + - semantic-model + summary: Load a Semantic Model + description: Returns the specified Semantic Model with its nested definition and audit data. + operationId: loadSemanticModel + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + put: + tags: + - semantic-model + summary: Alter a Semantic Model + description: >- + Applies the ordered updates atomically. The server validates and converts the complete + update batch before dispatch; if any update or the resulting model is invalid, none of the + updates is applied. Only replaceDefinition revalidates the complete definition. Source + existence, source columns, and source authorization checks are not yet implemented. + operationId: alterSemanticModel + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SemanticModelUpdatesRequest" + examples: + SemanticModelUpdatesRequest: + $ref: "#/components/examples/SemanticModelUpdatesRequest" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlterConflictResponse" + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + delete: + tags: + - semantic-model + summary: Drop a Semantic Model + description: >- + Drops the specified Semantic Model. A missing schema or Semantic Model is reported as a + successful response with dropped set to false. + operationId: dropSemanticModel + responses: + "200": + $ref: "./openapi.yaml#/components/responses/DropResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + description: Not Found - The target metalake or catalog does not exist + content: + application/vnd.gravitino.v1+json: + schema: + $ref: "./openapi.yaml#/components/schemas/ErrorModel" + examples: + NoSuchMetalakeException: + $ref: "./metalakes.yaml#/components/examples/NoSuchMetalakeException" + NoSuchCatalogException: + $ref: "./catalogs.yaml#/components/examples/NoSuchCatalogException" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelOptimisticLockResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/{semanticModel}/ossie: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + - $ref: "./openapi.yaml#/components/parameters/semanticModel" + + get: + tags: + - semantic-model + summary: Export a Semantic Model as an Apache Ossie document + description: >- + Exports the specified Semantic Model as a standalone Apache Ossie YAML or JSON document. + The response is downloadable document content rather than the native Gravitino response + envelope. The format query parameter selects the representation independently of the + Accept header, and its value is case-insensitive. + operationId: exportOssieDocument + parameters: + - name: format + in: query + description: The serialized document format + required: false + schema: + type: string + enum: + - yaml + - json + default: yaml + responses: + "200": + $ref: "#/components/responses/OssieSemanticModelDocumentResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + +components: + + schemas: + AIContext: + description: Additional context for AI tools, encoded as exactly one string or object value + oneOf: + - type: string + - $ref: "#/components/schemas/AIContextObject" + + AIContextObject: + type: object + description: >- + Structured context for AI tools. Unknown properties may contain any JSON value and are + retained losslessly in input order. + properties: + instructions: + type: string + description: Instructions for AI tools on how to use the entity + synonyms: + type: array + description: >- + Alternative names and terms. Omitting the property differs from supplying an empty + array. + items: + type: string + examples: + type: array + description: >- + Sample questions or use cases. Omitting the property differs from supplying an empty + array. + items: + type: string + additionalProperties: true + + SemanticModelSource: + type: object + description: >- + A governed Table or logical View expressed as catalog.schema.name. The endpoint metalake is + inherited and therefore is not included in this identifier. + required: + - namespace + - name + properties: + namespace: + type: array + minItems: 2 + maxItems: 2 + description: Exactly the catalog and schema containing the source, in that order + items: + type: string + minLength: 1 + name: + type: string + minLength: 1 + description: The source Table or logical View name + additionalProperties: false + + Dataset: + type: object + description: A logical dataset backed by a governed Gravitino Table or logical View + required: + - name + - source + properties: + name: + type: string + minLength: 1 + description: The dataset name, unique within the Semantic Model + source: + $ref: "#/components/schemas/SemanticModelSource" + primaryKey: + type: array + description: >- + Source columns that form the primary key. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: string + minLength: 1 + uniqueKeys: + type: array + description: >- + Source column sets that form unique keys. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: array + minItems: 1 + items: + type: string + minLength: 1 + description: + type: string + description: The human-readable dataset description + aiContext: + $ref: "#/components/schemas/AIContext" + fields: + type: array + description: >- + Ordered fields in the dataset. The property may be omitted; an explicitly supplied + empty array is retained as empty. + items: + $ref: "#/components/schemas/Field" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + OssieDataset: + type: object + description: >- + An Apache Ossie dataset backed by a governed Gravitino Table or logical View + required: + - name + - source + properties: + name: + type: string + minLength: 1 + description: The dataset name, unique within the Semantic Model + source: + type: string + minLength: 1 + description: >- + A catalog.schema.name source identifier. Segments containing dots or backticks use + backtick quoting, and a backtick inside a quoted segment is doubled. Query sources are + not supported. + primary_key: + type: array + description: >- + Source columns that form the primary key. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: string + minLength: 1 + unique_keys: + type: array + description: >- + Source column sets that form unique keys. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: array + minItems: 1 + items: + type: string + minLength: 1 + description: + type: string + description: The human-readable dataset description + ai_context: + $ref: "#/components/schemas/AIContext" + fields: + type: array + description: >- + Ordered fields in the dataset. The property may be omitted; an explicitly supplied + empty array is retained as empty. + items: + $ref: "#/components/schemas/OssieField" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + Field: + type: object + description: A row-level semantic attribute in a dataset + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The field name, unique within its dataset + expression: + $ref: "#/components/schemas/Expression" + dimension: + $ref: "#/components/schemas/Dimension" + label: + type: string + description: The display label used to categorize the field + description: + type: string + description: The human-readable field description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + aiContext: + $ref: "#/components/schemas/AIContext" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + Relationship: + type: object + description: A relationship between two datasets in the same Semantic Model + required: + - name + - from + - to + - fromColumns + - toColumns + properties: + name: + type: string + minLength: 1 + description: The relationship name, unique within the Semantic Model + from: + type: string + minLength: 1 + description: The source dataset name + to: + type: string + minLength: 1 + description: The target dataset name + fromColumns: + type: array + minItems: 1 + description: >- + Non-empty source columns. The array must have the same number of entries as toColumns. + items: + type: string + minLength: 1 + toColumns: + type: array + minItems: 1 + description: >- + Non-empty target columns. The array must have the same number of entries as + fromColumns. + items: + type: string + minLength: 1 + aiContext: + $ref: "#/components/schemas/AIContext" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + Metric: + type: object + description: A model-scoped quantitative measure + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The metric name, unique within the Semantic Model + expression: + $ref: "#/components/schemas/Expression" + description: + type: string + description: The human-readable metric description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + aiContext: + $ref: "#/components/schemas/AIContext" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + Expression: + type: object + description: An expression with one or more ordered dialect-specific representations + required: + - dialects + properties: + dialects: + type: array + minItems: 1 + description: Each dialect identifier may occur at most once + items: + $ref: "#/components/schemas/DialectExpression" + additionalProperties: false + + DialectExpression: + type: object + description: An expression written in a specific dialect + required: + - dialect + - expression + properties: + dialect: + type: string + minLength: 1 + description: >- + An open dialect identifier. ANSI_SQL, SNOWFLAKE, MDX, TABLEAU, DATABRICKS, MAQL, and + BIGQUERY are well-known Apache Ossie values; other non-empty identifiers are accepted + and preserved without conversion or fallback. + expression: + type: string + minLength: 1 + description: The non-empty dialect-specific expression text + additionalProperties: false + + Dimension: + type: object + description: >- + Dimension metadata for a field. An empty object is valid and remains distinct from an + omitted dimension. + properties: + isTime: + type: boolean + nullable: true + description: Whether consumers should treat the field as a time dimension + additionalProperties: false + + CustomExtension: + type: object + description: Vendor-specific attributes retained for Semantic Model interchange + required: + - vendorName + - data + properties: + vendorName: + type: string + description: The extension vendor name + data: + type: string + description: Opaque vendor-specific data retained as a string + additionalProperties: false + + OssieField: + type: object + description: A row-level semantic attribute in a dataset + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The field name, unique within its dataset + expression: + $ref: "#/components/schemas/Expression" + dimension: + $ref: "#/components/schemas/OssieDimension" + label: + type: string + description: The display label used to categorize the field + description: + type: string + description: The human-readable field description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + ai_context: + $ref: "#/components/schemas/AIContext" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + OssieRelationship: + type: object + description: A relationship between two datasets in the same Semantic Model + required: + - name + - from + - to + - from_columns + - to_columns + properties: + name: + type: string + minLength: 1 + description: The relationship name, unique within the Semantic Model + from: + type: string + minLength: 1 + description: The source dataset name + to: + type: string + minLength: 1 + description: The target dataset name + from_columns: + type: array + minItems: 1 + description: >- + Non-empty source columns. The array must have the same number of entries as to_columns. + items: + type: string + minLength: 1 + to_columns: + type: array + minItems: 1 + description: >- + Non-empty target columns. The array must have the same number of entries as + from_columns. + items: + type: string + minLength: 1 + ai_context: + $ref: "#/components/schemas/AIContext" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + OssieMetric: + type: object + description: A model-scoped quantitative measure + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The metric name, unique within the Semantic Model + expression: + $ref: "#/components/schemas/Expression" + description: + type: string + description: The human-readable metric description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + ai_context: + $ref: "#/components/schemas/AIContext" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + OssieDimension: + type: object + description: >- + Dimension metadata for a field. An empty object is valid and remains distinct from an + omitted dimension. + properties: + is_time: + type: boolean + description: Whether consumers should treat the field as a time dimension + additionalProperties: false + + OssieCustomExtension: + type: object + description: Vendor-specific attributes retained for Semantic Model interchange + required: + - vendor_name + - data + properties: + vendor_name: + type: string + description: The extension vendor name + data: + type: string + description: Opaque vendor-specific data retained as a string + additionalProperties: false + + SemanticModelDataType: + type: string + description: The exact wire value for a logical field or metric data type + enum: + - String + - Integer + - Decimal + - Float + - Boolean + - Date + - Time + - DateTime + - DateTimeTz + - Opaque + + SemanticModelDefinition: + type: object + description: The complete replaceable semantic definition, without entity metadata + required: + - datasets + properties: + aiContext: + $ref: "#/components/schemas/AIContext" + datasets: + type: array + minItems: 1 + description: The non-empty ordered datasets in the Semantic Model + items: + $ref: "#/components/schemas/Dataset" + relationships: + type: array + description: >- + Ordered relationships. The property may be omitted; an explicitly supplied empty array + is retained as empty. + items: + $ref: "#/components/schemas/Relationship" + metrics: + type: array + description: >- + Ordered metrics. The property may be omitted; an explicitly supplied empty array is + retained as empty. + items: + $ref: "#/components/schemas/Metric" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The root vendorName GRAVITINO_PROPERTIES is reserved and + cannot be supplied in a native definition. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + OssieSemanticModelDocument: + type: object + description: >- + A standalone Apache Ossie document. Unlike the native Gravitino response, its semantic + definition is at the document root and it contains no response envelope, audit data, or + direct properties object. + required: + - version + - name + - datasets + properties: + version: + type: string + minLength: 1 + description: >- + The non-blank Apache Ossie document version, stored in the ossie-version model property + on import. Export uses that property or defaults to 0.2.0.dev0 when it is absent. The + version is preserved without restricting it to a fixed allowlist. + name: + type: string + minLength: 1 + description: The Semantic Model name + description: + type: string + description: The human-readable Semantic Model description + ai_context: + $ref: "#/components/schemas/AIContext" + datasets: + type: array + minItems: 1 + description: The non-empty ordered datasets in the Semantic Model + items: + $ref: "#/components/schemas/OssieDataset" + relationships: + type: array + description: >- + Ordered relationships. The property may be omitted; an explicitly supplied empty array + is retained as empty. + items: + $ref: "#/components/schemas/OssieRelationship" + metrics: + type: array + description: >- + Ordered metrics. The property may be omitted; an explicitly supplied empty array is + retained as empty. + items: + $ref: "#/components/schemas/OssieMetric" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. At most one root GRAVITINO_PROPERTIES extension carries + Gravitino-specific properties as a JSON object encoded in a string, with string values + only. Import consumes this extension into model properties; an ossie-version value in + its data must match the document version. Export omits ossie-version from the extension + and writes it as version instead. Other extensions and nested GRAVITINO_PROPERTIES + extensions remain opaque. The property may be omitted; an explicitly supplied empty + array is normalized to an absent customExtensions in the native definition on import. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + SemanticModel: + type: object + description: A schema-scoped analytical Semantic Model with a nested semantic definition + required: + - name + - definition + - properties + - audit + properties: + name: + type: string + minLength: 1 + description: The Semantic Model name + comment: + type: string + nullable: true + description: The comment, or null when no comment is set Review Comment: [Nit] `SemanticModel.comment` is documented as `nullable: true` / "or null when no comment is set", but the server never emits `comment: null`: `SemanticModelDTO` is annotated `@JsonInclude(JsonInclude.Include.NON_NULL)` (`common/src/main/java/org/apache/gravitino/dto/semantic/SemanticModelDTO.java:38`) and the server's mapper independently applies `setSerializationInclusion(JsonInclude.Include.NON_NULL)` (`server-common/src/main/java/org/apache/gravitino/server/web/ObjectMapperProvider.java:112`), so an unset comment is absent from the payload. Suggest "The comment; the property is omitted when no comment is set" and dropping `nullable: true` on this one field. (`SemanticModelCreateRequest.comment` and `UpdateSemanticModelCommentRequest.newComment` are request fields and are correct as written - a null there really is accepted.) Raising it only because the rest of the file is careful about the omitted-vs-explicit distinction, e.g. the `Dimension` description at line 608. Verified by: reading SemanticModelDTO.java:36-72 and ObjectMapperProvider.java:100-115 on this branch. ########## docs/open-api/semantic-models.yaml: ########## @@ -0,0 +1,1588 @@ +# 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. + +--- + +paths: + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + get: + tags: + - semantic-model + summary: List Semantic Models + description: >- + Lists the Semantic Models in a schema. Semantic Models are supported only for relational + catalogs. Each returned identifier uses the full metalake.catalog.schema.name namespace. + operationId: listSemanticModels + responses: + "200": + $ref: "#/components/responses/SemanticModelListResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + post: + tags: + - semantic-model + summary: Create a Semantic Model + description: >- + Creates a schema-scoped Semantic Model in a relational catalog. The complete definition is + validated before the model is stored, including source identifier shape. Source existence, + source columns, and source authorization checks are not yet implemented. + operationId: createSemanticModel + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SemanticModelCreateRequest" + examples: + SemanticModelCreateRequest: + $ref: "#/components/examples/SemanticModelCreateRequest" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlreadyExistsResponse" + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/ossie: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + + post: + tags: + - semantic-model + summary: Import an Apache Ossie Semantic Model + description: >- + Imports one standalone Apache Ossie document and creates the represented Semantic Model. + The request body is the raw JSON or YAML document, not a JSON-encoded string. Content-Type + selects the parser, and parsing does not fall back to another format. + operationId: importOssieDocument + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + application/yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + application/x-yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + text/yaml: + schema: + $ref: "#/components/schemas/OssieSemanticModelDocument" + examples: + OssieSemanticModelDocument: + $ref: "#/components/examples/OssieSemanticModelDocument" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelParentNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlreadyExistsResponse" + "415": + description: >- + Unsupported Media Type - Content-Type must be application/json, application/yaml, + application/x-yaml, or text/yaml + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/{semanticModel}: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + - $ref: "./openapi.yaml#/components/parameters/semanticModel" + + get: + tags: + - semantic-model + summary: Load a Semantic Model + description: Returns the specified Semantic Model with its nested definition and audit data. + operationId: loadSemanticModel + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + put: + tags: + - semantic-model + summary: Alter a Semantic Model + description: >- + Applies the ordered updates atomically. The server validates and converts the complete + update batch before dispatch; if any update or the resulting model is invalid, none of the + updates is applied. Only replaceDefinition revalidates the complete definition. Source + existence, source columns, and source authorization checks are not yet implemented. + operationId: alterSemanticModel + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SemanticModelUpdatesRequest" + examples: + SemanticModelUpdatesRequest: + $ref: "#/components/examples/SemanticModelUpdatesRequest" + responses: + "200": + $ref: "#/components/responses/SemanticModelResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelAlterConflictResponse" + "502": + $ref: "#/components/responses/SemanticModelConnectionFailedResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + delete: + tags: + - semantic-model + summary: Drop a Semantic Model + description: >- + Drops the specified Semantic Model. A missing schema or Semantic Model is reported as a + successful response with dropped set to false. + operationId: dropSemanticModel + responses: + "200": + $ref: "./openapi.yaml#/components/responses/DropResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + description: Not Found - The target metalake or catalog does not exist + content: + application/vnd.gravitino.v1+json: + schema: + $ref: "./openapi.yaml#/components/schemas/ErrorModel" + examples: + NoSuchMetalakeException: + $ref: "./metalakes.yaml#/components/examples/NoSuchMetalakeException" + NoSuchCatalogException: + $ref: "./catalogs.yaml#/components/examples/NoSuchCatalogException" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "409": + $ref: "#/components/responses/SemanticModelOptimisticLockResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + + /metalakes/{metalake}/catalogs/{catalog}/schemas/{schema}/semantic-models/{semanticModel}/ossie: + parameters: + - $ref: "./openapi.yaml#/components/parameters/metalake" + - $ref: "./openapi.yaml#/components/parameters/catalog" + - $ref: "./openapi.yaml#/components/parameters/schema" + - $ref: "./openapi.yaml#/components/parameters/semanticModel" + + get: + tags: + - semantic-model + summary: Export a Semantic Model as an Apache Ossie document + description: >- + Exports the specified Semantic Model as a standalone Apache Ossie YAML or JSON document. + The response is downloadable document content rather than the native Gravitino response + envelope. The format query parameter selects the representation independently of the + Accept header, and its value is case-insensitive. + operationId: exportOssieDocument + parameters: + - name: format + in: query + description: The serialized document format + required: false + schema: + type: string + enum: + - yaml + - json + default: yaml + responses: + "200": + $ref: "#/components/responses/OssieSemanticModelDocumentResponse" + "400": + $ref: "#/components/responses/SemanticModelBadRequestResponse" + "403": + $ref: "#/components/responses/SemanticModelForbiddenResponse" + "404": + $ref: "#/components/responses/SemanticModelNotFoundResponse" + "405": + $ref: "#/components/responses/SemanticModelUnsupportedCatalogResponse" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + +components: + + schemas: + AIContext: + description: Additional context for AI tools, encoded as exactly one string or object value + oneOf: + - type: string + - $ref: "#/components/schemas/AIContextObject" + + AIContextObject: + type: object + description: >- + Structured context for AI tools. Unknown properties may contain any JSON value and are + retained losslessly in input order. + properties: + instructions: + type: string + description: Instructions for AI tools on how to use the entity + synonyms: + type: array + description: >- + Alternative names and terms. Omitting the property differs from supplying an empty + array. + items: + type: string + examples: + type: array + description: >- + Sample questions or use cases. Omitting the property differs from supplying an empty + array. + items: + type: string + additionalProperties: true + + SemanticModelSource: + type: object + description: >- + A governed Table or logical View expressed as catalog.schema.name. The endpoint metalake is + inherited and therefore is not included in this identifier. + required: + - namespace + - name + properties: + namespace: + type: array + minItems: 2 + maxItems: 2 + description: Exactly the catalog and schema containing the source, in that order + items: + type: string + minLength: 1 + name: + type: string + minLength: 1 + description: The source Table or logical View name + additionalProperties: false + + Dataset: + type: object + description: A logical dataset backed by a governed Gravitino Table or logical View + required: + - name + - source + properties: + name: + type: string + minLength: 1 + description: The dataset name, unique within the Semantic Model + source: + $ref: "#/components/schemas/SemanticModelSource" + primaryKey: + type: array + description: >- + Source columns that form the primary key. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: string + minLength: 1 + uniqueKeys: + type: array + description: >- + Source column sets that form unique keys. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: array + minItems: 1 + items: + type: string + minLength: 1 + description: + type: string + description: The human-readable dataset description + aiContext: + $ref: "#/components/schemas/AIContext" + fields: + type: array + description: >- + Ordered fields in the dataset. The property may be omitted; an explicitly supplied + empty array is retained as empty. + items: + $ref: "#/components/schemas/Field" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + OssieDataset: + type: object + description: >- + An Apache Ossie dataset backed by a governed Gravitino Table or logical View + required: + - name + - source + properties: + name: + type: string + minLength: 1 + description: The dataset name, unique within the Semantic Model + source: + type: string + minLength: 1 + description: >- + A catalog.schema.name source identifier. Segments containing dots or backticks use + backtick quoting, and a backtick inside a quoted segment is doubled. Query sources are + not supported. + primary_key: + type: array + description: >- + Source columns that form the primary key. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: string + minLength: 1 + unique_keys: + type: array + description: >- + Source column sets that form unique keys. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + type: array + minItems: 1 + items: + type: string + minLength: 1 + description: + type: string + description: The human-readable dataset description + ai_context: + $ref: "#/components/schemas/AIContext" + fields: + type: array + description: >- + Ordered fields in the dataset. The property may be omitted; an explicitly supplied + empty array is retained as empty. + items: + $ref: "#/components/schemas/OssieField" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + Field: + type: object + description: A row-level semantic attribute in a dataset + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The field name, unique within its dataset + expression: + $ref: "#/components/schemas/Expression" + dimension: + $ref: "#/components/schemas/Dimension" + label: + type: string + description: The display label used to categorize the field + description: + type: string + description: The human-readable field description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + aiContext: + $ref: "#/components/schemas/AIContext" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + Relationship: + type: object + description: A relationship between two datasets in the same Semantic Model + required: + - name + - from + - to + - fromColumns + - toColumns + properties: + name: + type: string + minLength: 1 + description: The relationship name, unique within the Semantic Model + from: + type: string + minLength: 1 + description: The source dataset name + to: + type: string + minLength: 1 + description: The target dataset name + fromColumns: + type: array + minItems: 1 + description: >- + Non-empty source columns. The array must have the same number of entries as toColumns. + items: + type: string + minLength: 1 + toColumns: + type: array + minItems: 1 + description: >- + Non-empty target columns. The array must have the same number of entries as + fromColumns. + items: + type: string + minLength: 1 + aiContext: + $ref: "#/components/schemas/AIContext" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + Metric: + type: object + description: A model-scoped quantitative measure + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The metric name, unique within the Semantic Model + expression: + $ref: "#/components/schemas/Expression" + description: + type: string + description: The human-readable metric description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + aiContext: + $ref: "#/components/schemas/AIContext" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + Expression: + type: object + description: An expression with one or more ordered dialect-specific representations + required: + - dialects + properties: + dialects: + type: array + minItems: 1 + description: Each dialect identifier may occur at most once + items: + $ref: "#/components/schemas/DialectExpression" + additionalProperties: false + + DialectExpression: + type: object + description: An expression written in a specific dialect + required: + - dialect + - expression + properties: + dialect: + type: string + minLength: 1 + description: >- + An open dialect identifier. ANSI_SQL, SNOWFLAKE, MDX, TABLEAU, DATABRICKS, MAQL, and + BIGQUERY are well-known Apache Ossie values; other non-empty identifiers are accepted + and preserved without conversion or fallback. + expression: + type: string + minLength: 1 + description: The non-empty dialect-specific expression text + additionalProperties: false + + Dimension: + type: object + description: >- + Dimension metadata for a field. An empty object is valid and remains distinct from an + omitted dimension. + properties: + isTime: + type: boolean + nullable: true + description: Whether consumers should treat the field as a time dimension + additionalProperties: false + + CustomExtension: + type: object + description: Vendor-specific attributes retained for Semantic Model interchange + required: + - vendorName + - data + properties: + vendorName: + type: string + description: The extension vendor name + data: + type: string + description: Opaque vendor-specific data retained as a string + additionalProperties: false + + OssieField: + type: object + description: A row-level semantic attribute in a dataset + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The field name, unique within its dataset + expression: + $ref: "#/components/schemas/Expression" + dimension: + $ref: "#/components/schemas/OssieDimension" + label: + type: string + description: The display label used to categorize the field + description: + type: string + description: The human-readable field description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + ai_context: + $ref: "#/components/schemas/AIContext" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + OssieRelationship: + type: object + description: A relationship between two datasets in the same Semantic Model + required: + - name + - from + - to + - from_columns + - to_columns + properties: + name: + type: string + minLength: 1 + description: The relationship name, unique within the Semantic Model + from: + type: string + minLength: 1 + description: The source dataset name + to: + type: string + minLength: 1 + description: The target dataset name + from_columns: + type: array + minItems: 1 + description: >- + Non-empty source columns. The array must have the same number of entries as to_columns. + items: + type: string + minLength: 1 + to_columns: + type: array + minItems: 1 + description: >- + Non-empty target columns. The array must have the same number of entries as + from_columns. + items: + type: string + minLength: 1 + ai_context: + $ref: "#/components/schemas/AIContext" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + OssieMetric: + type: object + description: A model-scoped quantitative measure + required: + - name + - expression + properties: + name: + type: string + minLength: 1 + description: The metric name, unique within the Semantic Model + expression: + $ref: "#/components/schemas/Expression" + description: + type: string + description: The human-readable metric description + datatype: + $ref: "#/components/schemas/SemanticModelDataType" + ai_context: + $ref: "#/components/schemas/AIContext" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. The property may be omitted; an explicitly supplied empty + array is retained as empty. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + OssieDimension: + type: object + description: >- + Dimension metadata for a field. An empty object is valid and remains distinct from an + omitted dimension. + properties: + is_time: + type: boolean + description: Whether consumers should treat the field as a time dimension + additionalProperties: false + + OssieCustomExtension: + type: object + description: Vendor-specific attributes retained for Semantic Model interchange + required: + - vendor_name + - data + properties: + vendor_name: + type: string + description: The extension vendor name + data: + type: string + description: Opaque vendor-specific data retained as a string + additionalProperties: false + + SemanticModelDataType: + type: string + description: The exact wire value for a logical field or metric data type + enum: + - String + - Integer + - Decimal + - Float + - Boolean + - Date + - Time + - DateTime + - DateTimeTz + - Opaque + + SemanticModelDefinition: + type: object + description: The complete replaceable semantic definition, without entity metadata + required: + - datasets + properties: + aiContext: + $ref: "#/components/schemas/AIContext" + datasets: + type: array + minItems: 1 + description: The non-empty ordered datasets in the Semantic Model + items: + $ref: "#/components/schemas/Dataset" + relationships: + type: array + description: >- + Ordered relationships. The property may be omitted; an explicitly supplied empty array + is retained as empty. + items: + $ref: "#/components/schemas/Relationship" + metrics: + type: array + description: >- + Ordered metrics. The property may be omitted; an explicitly supplied empty array is + retained as empty. + items: + $ref: "#/components/schemas/Metric" + customExtensions: + type: array + description: >- + Vendor-specific extensions. The root vendorName GRAVITINO_PROPERTIES is reserved and + cannot be supplied in a native definition. The property may be omitted; an explicitly + supplied empty array is retained as empty. + items: + $ref: "#/components/schemas/CustomExtension" + additionalProperties: false + + OssieSemanticModelDocument: + type: object + description: >- + A standalone Apache Ossie document. Unlike the native Gravitino response, its semantic + definition is at the document root and it contains no response envelope, audit data, or + direct properties object. + required: + - version + - name + - datasets + properties: + version: + type: string + minLength: 1 + description: >- + The non-blank Apache Ossie document version, stored in the ossie-version model property + on import. Export uses that property or defaults to 0.2.0.dev0 when it is absent. The + version is preserved without restricting it to a fixed allowlist. + name: + type: string + minLength: 1 + description: The Semantic Model name + description: + type: string + description: The human-readable Semantic Model description + ai_context: + $ref: "#/components/schemas/AIContext" + datasets: + type: array + minItems: 1 + description: The non-empty ordered datasets in the Semantic Model + items: + $ref: "#/components/schemas/OssieDataset" + relationships: + type: array + description: >- + Ordered relationships. The property may be omitted; an explicitly supplied empty array + is retained as empty. + items: + $ref: "#/components/schemas/OssieRelationship" + metrics: + type: array + description: >- + Ordered metrics. The property may be omitted; an explicitly supplied empty array is + retained as empty. + items: + $ref: "#/components/schemas/OssieMetric" + custom_extensions: + type: array + description: >- + Vendor-specific extensions. At most one root GRAVITINO_PROPERTIES extension carries + Gravitino-specific properties as a JSON object encoded in a string, with string values + only. Import consumes this extension into model properties; an ossie-version value in + its data must match the document version. Export omits ossie-version from the extension + and writes it as version instead. Other extensions and nested GRAVITINO_PROPERTIES + extensions remain opaque. The property may be omitted; an explicitly supplied empty + array is normalized to an absent customExtensions in the native definition on import. + items: + $ref: "#/components/schemas/OssieCustomExtension" + additionalProperties: false + + SemanticModel: + type: object + description: A schema-scoped analytical Semantic Model with a nested semantic definition + required: + - name + - definition + - properties + - audit + properties: + name: + type: string + minLength: 1 + description: The Semantic Model name + comment: + type: string + nullable: true + description: The comment, or null when no comment is set + definition: + $ref: "#/components/schemas/SemanticModelDefinition" + properties: + type: object + description: Gravitino-specific Semantic Model properties, including the Ossie version + additionalProperties: + type: string + audit: + $ref: "./openapi.yaml#/components/schemas/Audit" + additionalProperties: false + + SemanticModelCreateRequest: + type: object + description: The request to create a Semantic Model + required: + - name + - definition + properties: + name: + type: string + minLength: 1 + description: The non-blank Semantic Model name + comment: + type: string + nullable: true + description: The optional Semantic Model comment + definition: + $ref: "#/components/schemas/SemanticModelDefinition" + properties: + type: object + nullable: true + description: >- + Optional Gravitino-specific properties. Omitted or null properties use the defaults. + The ossie-version property must be non-blank and defaults to 0.2.0.dev0. + additionalProperties: + type: string + additionalProperties: false + + SemanticModelUpdatesRequest: + type: object + description: A non-empty ordered update batch applied atomically + required: + - updates + properties: + updates: + type: array + minItems: 1 + items: + $ref: "#/components/schemas/SemanticModelUpdateRequest" + additionalProperties: false + + SemanticModelUpdateRequest: + description: One polymorphic Semantic Model update + oneOf: + - $ref: "#/components/schemas/RenameSemanticModelRequest" + - $ref: "#/components/schemas/UpdateSemanticModelCommentRequest" + - $ref: "#/components/schemas/SetSemanticModelPropertyRequest" + - $ref: "#/components/schemas/RemoveSemanticModelPropertyRequest" + - $ref: "#/components/schemas/ReplaceSemanticModelDefinitionRequest" + discriminator: + propertyName: "@type" + mapping: + rename: "#/components/schemas/RenameSemanticModelRequest" + updateComment: "#/components/schemas/UpdateSemanticModelCommentRequest" + setProperty: "#/components/schemas/SetSemanticModelPropertyRequest" + removeProperty: "#/components/schemas/RemoveSemanticModelPropertyRequest" + replaceDefinition: "#/components/schemas/ReplaceSemanticModelDefinitionRequest" + + RenameSemanticModelRequest: + type: object + description: Renames the Semantic Model + required: + - "@type" + - newName + properties: + "@type": + type: string + enum: + - rename + newName: + type: string + minLength: 1 + description: The new non-blank Semantic Model name + example: { + "@type": "rename", + "newName": "sales_model_v2" + } + + UpdateSemanticModelCommentRequest: + type: object + description: >- + Replaces the comment. An omitted or null newComment clears the comment; an explicit empty + string is stored as an empty comment. + required: + - "@type" + properties: + "@type": + type: string + enum: + - updateComment + newComment: + type: string + nullable: true + description: The new comment, null to clear it, or an empty string to retain empty + example: { + "@type": "updateComment", + "newComment": "Updated sales definitions" + } + + SetSemanticModelPropertyRequest: + type: object + description: Sets or replaces one Gravitino-specific property + required: + - "@type" + - property + - value + properties: + "@type": + type: string + enum: + - setProperty + property: + type: string + minLength: 1 + description: The non-blank property name + value: + type: string + description: The property value; an empty string is valid + example: { + "@type": "setProperty", + "property": "domain", + "value": "sales" + } + + RemoveSemanticModelPropertyRequest: + type: object + description: Removes one Gravitino-specific property if it exists + required: + - "@type" + - property + properties: + "@type": + type: string + enum: + - removeProperty + property: + type: string + minLength: 1 + description: The non-blank property name + example: { + "@type": "removeProperty", + "property": "legacy" + } + + ReplaceSemanticModelDefinitionRequest: + type: object + description: Replaces and validates the complete nested definition atomically + required: + - "@type" + - definition + properties: + "@type": + type: string + enum: + - replaceDefinition + definition: + $ref: "#/components/schemas/SemanticModelDefinition" + example: { + "@type": "replaceDefinition", + "definition": { + "datasets": [ + { + "name": "orders", + "source": { + "namespace": ["sales", "mart"], + "name": "orders" + }, + "fields": [] + } + ], + "relationships": [], + "metrics": [], + "customExtensions": [] + } + } + + responses: + SemanticModelListResponse: + description: Returns the Semantic Model identifiers in the schema + content: + application/vnd.gravitino.v1+json: + schema: + type: object + required: + - code + - identifiers + properties: + code: + type: integer + format: int32 + description: Status code of the response + enum: + - 0 + identifiers: + type: array + description: Full Semantic Model identifiers + items: + $ref: "./openapi.yaml#/components/schemas/NameIdentifier" + additionalProperties: false + examples: + SemanticModelListResponse: + $ref: "#/components/examples/SemanticModelListResponse" + + SemanticModelResponse: + description: Returns the Semantic Model object with its nested definition + content: + application/vnd.gravitino.v1+json: + schema: + type: object + required: + - code + - semanticModel + properties: + code: + type: integer + format: int32 + description: Status code of the response + enum: + - 0 + semanticModel: + $ref: "#/components/schemas/SemanticModel" + additionalProperties: false + examples: + SemanticModelResponse: + $ref: "#/components/examples/SemanticModelResponse" + + OssieSemanticModelDocumentResponse: + description: Returns a standalone Apache Ossie document in the requested format + headers: + Content-Disposition: + description: Attachment filename ending in .ossie.yaml or .ossie.json Review Comment: [Nit] The Content-Disposition description does not mention that the filename is sanitized. `ossieContentDisposition` runs `semanticModel.replaceAll("[^A-Za-z0-9._-]", "_")` before appending the extension (`server/src/main/java/org/apache/gravitino/server/web/rest/SemanticModelOperations.java:445-449`), so a model named `sales model` or `sales/model` downloads as `sales_model.ossie.yaml`. A client cannot derive the filename from the model name, which is worth one clause here since the example at line 1145 shows a name that happens to need no escaping. Verified by: reading ossieContentDisposition at SemanticModelOperations.java:445-449 on this branch. -- 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]
