diff --git a/open-api/rest-catalog-open-api.py b/open-api/rest-catalog-open-api.py index 99fe855147c8..a1e08b5ad441 100644 --- a/open-api/rest-catalog-open-api.py +++ b/open-api/rest-catalog-open-api.py @@ -152,6 +152,11 @@ class ExpressionType(RootModel[str]): class TrueExpression(BaseModel): + """ + Deprecated. Use the bare boolean literal `true` as a predicate instead. Retained for backward compatibility with older clients per the Iceberg Expressions spec (Appendix B, JSON serialization). + + """ + type: Literal['true'] = Field( ..., examples=[ @@ -181,6 +186,11 @@ class TrueExpression(BaseModel): class FalseExpression(BaseModel): + """ + Deprecated. Use the bare boolean literal `false` as a predicate instead. Retained for backward compatibility with older clients per the Iceberg Expressions spec (Appendix B, JSON serialization). + + """ + type: Literal['false'] = Field( ..., examples=[ @@ -209,10 +219,124 @@ class FalseExpression(BaseModel): ) +class FieldReference1(BaseModel): + """ + A reference to a field per Iceberg Expressions spec, Appendix B. Either a bound reference (by field ID) or an unbound reference (by name). The context in which an expression is used determines which form is valid. + + """ + + model_config = ConfigDict( + extra='forbid', + ) + type: Literal['reference'] + id: int + + +class FieldReference2(BaseModel): + """ + A reference to a field per Iceberg Expressions spec, Appendix B. Either a bound reference (by field ID) or an unbound reference (by name). The context in which an expression is used determines which form is valid. + + """ + + model_config = ConfigDict( + extra='forbid', + ) + type: Literal['reference'] + name: str + + +class FieldReference(RootModel[FieldReference1 | FieldReference2]): + root: FieldReference1 | FieldReference2 = Field( + ..., + description='A reference to a field per Iceberg Expressions spec, Appendix B. Either a bound reference (by field ID) or an unbound reference (by name). The context in which an expression is used determines which form is valid.\n', + ) + + +class FunctionReference1(RootModel[str]): + root: str = Field( + ..., + description='A reference to a function per Iceberg Expressions spec, Appendix B. Four JSON forms: a bare name (single-part identifier), a list of names (multi-part identifier), an object with an identifier, or an object with both a catalog and an identifier.\n', + min_length=1, + ) + + +class FunctionReference2Item(RootModel[str]): + root: str = Field(..., min_length=1) + + +class FunctionReference2(RootModel[list[FunctionReference2Item]]): + root: list[FunctionReference2Item] = Field( + ..., + description='A reference to a function per Iceberg Expressions spec, Appendix B. Four JSON forms: a bare name (single-part identifier), a list of names (multi-part identifier), an object with an identifier, or an object with both a catalog and an identifier.\n', + min_length=1, + ) + + +class IdentifierItem(RootModel[str]): + root: str = Field(..., min_length=1) + + +class FunctionReference3(BaseModel): + """ + A reference to a function per Iceberg Expressions spec, Appendix B. Four JSON forms: a bare name (single-part identifier), a list of names (multi-part identifier), an object with an identifier, or an object with both a catalog and an identifier. + + """ + + model_config = ConfigDict( + extra='forbid', + ) + identifier: list[IdentifierItem] = Field(..., min_length=1) + + +class FunctionReference4(BaseModel): + """ + A reference to a function per Iceberg Expressions spec, Appendix B. Four JSON forms: a bare name (single-part identifier), a list of names (multi-part identifier), an object with an identifier, or an object with both a catalog and an identifier. + + """ + + model_config = ConfigDict( + extra='forbid', + ) + catalog: str + identifier: list[IdentifierItem] = Field(..., min_length=1) + + +class FunctionReference( + RootModel[ + FunctionReference1 + | FunctionReference2 + | FunctionReference3 + | FunctionReference4 + ] +): + root: ( + FunctionReference1 + | FunctionReference2 + | FunctionReference3 + | FunctionReference4 + ) = Field( + ..., + description='A reference to a function per Iceberg Expressions spec, Appendix B. Four JSON forms: a bare name (single-part identifier), a list of names (multi-part identifier), an object with an identifier, or an object with both a catalog and an identifier.\n', + ) + + class Reference(RootModel[str]): root: str = Field(..., examples=[['column-name']]) +class DeprecatedReference(BaseModel): + """ + Deprecated backward-compatibility form of a field reference used in older REST predicates. Use FieldReference instead per Iceberg Expressions spec, Appendix B (Backward compatibility). + + """ + + model_config = ConfigDict( + extra='forbid', + ) + type: Literal['reference'] + term: str + + class Transform(RootModel[str]): root: str = Field( ..., @@ -1135,10 +1259,46 @@ class RenameTableRequest(BaseModel): destination: TableIdentifier -class TransformTerm(BaseModel): - type: Literal['transform'] - transform: Transform - term: Reference +class Literal1(BaseModel): + """ + A literal value expression per Iceberg Expressions spec, Appendix B. Three JSON forms are accepted: a bare scalar value, a typed literal object without a data-type, or a typed literal object with an explicit data-type. + + """ + + model_config = ConfigDict( + extra='forbid', + ) + type: Literal['literal'] + value: PrimitiveTypeValue + data_type: PrimitiveType | None = Field(None, alias='data-type') + + +class LiteralModel(RootModel[str | float | bool | Literal1]): + root: str | float | bool | Literal1 = Field( + ..., + description='A literal value expression per Iceberg Expressions spec, Appendix B. Three JSON forms are accepted: a bare scalar value, a typed literal object without a data-type, or a typed literal object with an explicit data-type.\n', + ) + + +class Literals1(BaseModel): + """ + A set of literal values per Iceberg Expressions spec, Appendix B. Two JSON forms: a bare array of literals, or a typed object with an explicit data-type applied to all values. + + """ + + model_config = ConfigDict( + extra='forbid', + ) + type: Literal['literals'] + values: list[PrimitiveTypeValue] + data_type: PrimitiveType = Field(..., alias='data-type') + + +class Literals(RootModel[list[LiteralModel] | Literals1]): + root: list[LiteralModel] | Literals1 = Field( + ..., + description='A set of literal values per Iceberg Expressions spec, Appendix B. Two JSON forms: a bare array of literals, or a typed object with an explicit data-type applied to all values.\n', + ) class SetPartitionStatisticsUpdate(BaseUpdate): @@ -1247,10 +1407,6 @@ class FetchScanTasksRequest(BaseModel): plan_task: PlanTask = Field(..., alias='plan-task') -class Term(RootModel[Reference | TransformTerm]): - root: Reference | TransformTerm - - class SetStatisticsUpdate(BaseUpdate): action: Literal['set-statistics'] snapshot_id: int | None = Field( @@ -1286,7 +1442,104 @@ class FunctionDefinitionVersion(BaseModel): ) -class UnaryExpression(BaseModel): +class StructField(BaseModel): + id: int + name: str + type: Type + required: bool + doc: str | None = None + initial_default: PrimitiveTypeValue | None = Field(None, alias='initial-default') + write_default: PrimitiveTypeValue | None = Field(None, alias='write-default') + + +class StructType(BaseModel): + type: Literal['struct'] + fields: list[StructField] + + +class ListType(BaseModel): + type: Literal['list'] + element_id: int = Field(..., alias='element-id') + element: Type + element_required: bool = Field(..., alias='element-required') + + +class MapType(BaseModel): + type: Literal['map'] + key_id: int = Field(..., alias='key-id') + key: Type + value_id: int = Field(..., alias='value-id') + value: Type + value_required: bool = Field(..., alias='value-required') + + +class AndOrExpression(BaseModel): + type: Literal['and', 'or'] = Field( + ..., + examples=[ + [ + 'true', + 'false', + 'eq', + 'and', + 'or', + 'not', + 'in', + 'not-in', + 'lt', + 'lt-eq', + 'gt', + 'gt-eq', + 'not-eq', + 'starts-with', + 'not-starts-with', + 'is-null', + 'not-null', + 'is-nan', + 'not-nan', + ] + ], + ) + left: Expression + right: Expression + + +class NotExpression(BaseModel): + type: Literal['not'] = Field( + ..., + examples=[ + [ + 'true', + 'false', + 'eq', + 'and', + 'or', + 'not', + 'in', + 'not-in', + 'lt', + 'lt-eq', + 'gt', + 'gt-eq', + 'not-eq', + 'starts-with', + 'not-starts-with', + 'is-null', + 'not-null', + 'is-nan', + 'not-nan', + ] + ], + ) + child: Expression + + +class UnaryPredicate(BaseModel): + """ + A predicate that tests a single value expression. Replaces the deprecated UnaryExpression that used 'term'. + + """ + type: Literal['is-null', 'not-null', 'is-nan', 'not-nan'] = Field( ..., examples=[ @@ -1313,10 +1566,15 @@ class UnaryExpression(BaseModel): ] ], ) - term: Term + child: ValueExpression -class LiteralExpression(BaseModel): +class ComparisonPredicate(BaseModel): + """ + A predicate that compares two value expressions. Replaces the deprecated LiteralExpression that used 'term' and 'value'. + + """ + type: Literal[ 'lt', 'lt-eq', 'gt', 'gt-eq', 'eq', 'not-eq', 'starts-with', 'not-starts-with' ] = Field( @@ -1345,11 +1603,16 @@ class LiteralExpression(BaseModel): ] ], ) - term: Term - value: PrimitiveTypeValue + left: ValueExpression + right: ValueExpression -class SetExpression(BaseModel): +class SetPredicate(BaseModel): + """ + A predicate that tests whether a value expression is in a set of literals. Replaces the deprecated SetExpression that used 'term'. + + """ + type: Literal['in', 'not-in'] = Field( ..., examples=[ @@ -1376,43 +1639,68 @@ class SetExpression(BaseModel): ] ], ) - term: Term - values: list[PrimitiveTypeValue] + child: ValueExpression + values: Literals -class StructField(BaseModel): - id: int - name: str - type: Type - required: bool - doc: str | None = None - initial_default: PrimitiveTypeValue | None = Field(None, alias='initial-default') - write_default: PrimitiveTypeValue | None = Field(None, alias='write-default') +class Apply(BaseModel): + """ + A function application per Iceberg Expressions spec, Appendix B. Represents the result of calling a function on zero or more value expressions or predicates. + """ -class StructType(BaseModel): - type: Literal['struct'] - fields: list[StructField] + model_config = ConfigDict( + extra='forbid', + ) + type: Literal['apply'] + function: FunctionReference + arguments: list[ValueExpression | Expression] -class ListType(BaseModel): - type: Literal['list'] - element_id: int = Field(..., alias='element-id') - element: Type - element_required: bool = Field(..., alias='element-required') +class UnaryExpression(BaseModel): + """ + Deprecated. Use UnaryPredicate with 'child' (a ValueExpression) instead. Retained for backward compatibility with older clients per the Iceberg Expressions spec (Appendix B, Backward compatibility). + """ -class MapType(BaseModel): - type: Literal['map'] - key_id: int = Field(..., alias='key-id') - key: Type - value_id: int = Field(..., alias='value-id') - value: Type - value_required: bool = Field(..., alias='value-required') + type: Literal['is-null', 'not-null', 'is-nan', 'not-nan'] = Field( + ..., + examples=[ + [ + 'true', + 'false', + 'eq', + 'and', + 'or', + 'not', + 'in', + 'not-in', + 'lt', + 'lt-eq', + 'gt', + 'gt-eq', + 'not-eq', + 'starts-with', + 'not-starts-with', + 'is-null', + 'not-null', + 'is-nan', + 'not-nan', + ] + ], + ) + term: Term -class AndOrExpression(BaseModel): - type: Literal['and', 'or'] = Field( +class LiteralExpression(BaseModel): + """ + Deprecated. Use ComparisonPredicate with 'left' and 'right' (ValueExpressions) instead. Retained for backward compatibility with older clients per the Iceberg Expressions spec (Appendix B, Backward compatibility). + + """ + + type: Literal[ + 'lt', 'lt-eq', 'gt', 'gt-eq', 'eq', 'not-eq', 'starts-with', 'not-starts-with' + ] = Field( ..., examples=[ [ @@ -1438,12 +1726,17 @@ class AndOrExpression(BaseModel): ] ], ) - left: Expression - right: Expression + term: Term + value: LiteralModel -class NotExpression(BaseModel): - type: Literal['not'] = Field( +class SetExpression(BaseModel): + """ + Deprecated. Use SetPredicate with 'child' (a ValueExpression) instead. Retained for backward compatibility with older clients per the Iceberg Expressions spec (Appendix B, Backward compatibility). + + """ + + type: Literal['in', 'not-in'] = Field( ..., examples=[ [ @@ -1469,7 +1762,14 @@ class NotExpression(BaseModel): ] ], ) - child: Expression + term: Term + values: Literals + + +class TransformTerm(BaseModel): + type: Literal['transform'] + transform: Transform + term: Term class TableMetadata(BaseModel): @@ -1906,28 +2206,47 @@ class Type(RootModel[PrimitiveType | StructType | ListType | MapType]): root: PrimitiveType | StructType | ListType | MapType +class ValueExpression(RootModel[LiteralModel | FieldReference | Apply]): + root: LiteralModel | FieldReference | Apply = Field( + ..., + description='A value expression per Iceberg Expressions spec, Appendix B: a literal, a field reference, or a function application. The result type is determined when the expression is bound to an input schema.\n', + ) + + class Expression( RootModel[ - TrueExpression + bool + | TrueExpression | FalseExpression | AndOrExpression | NotExpression - | SetExpression - | LiteralExpression + | UnaryPredicate + | ComparisonPredicate + | SetPredicate | UnaryExpression + | LiteralExpression + | SetExpression ] ): root: ( - TrueExpression + bool + | TrueExpression | FalseExpression | AndOrExpression | NotExpression - | SetExpression - | LiteralExpression + | UnaryPredicate + | ComparisonPredicate + | SetPredicate | UnaryExpression + | LiteralExpression + | SetExpression ) +class Term(RootModel[Reference | TransformTerm | DeprecatedReference]): + root: Reference | TransformTerm | DeprecatedReference + + class TableUpdate( RootModel[ AssignUUIDUpdate @@ -2086,6 +2405,14 @@ class PlanTableScanResult( MapType.model_rebuild() AndOrExpression.model_rebuild() NotExpression.model_rebuild() +UnaryPredicate.model_rebuild() +ComparisonPredicate.model_rebuild() +SetPredicate.model_rebuild() +Apply.model_rebuild() +UnaryExpression.model_rebuild() +LiteralExpression.model_rebuild() +SetExpression.model_rebuild() +TransformTerm.model_rebuild() TableMetadata.model_rebuild() ViewMetadata.model_rebuild() AddSchemaUpdate.model_rebuild() diff --git a/open-api/rest-catalog-open-api.yaml b/open-api/rest-catalog-open-api.yaml index 419041d12a87..681f827863db 100644 --- a/open-api/rest-catalog-open-api.yaml +++ b/open-api/rest-catalog-open-api.yaml @@ -2530,13 +2530,17 @@ components: Expression: oneOf: + - type: boolean - $ref: '#/components/schemas/TrueExpression' - $ref: '#/components/schemas/FalseExpression' - $ref: '#/components/schemas/AndOrExpression' - $ref: '#/components/schemas/NotExpression' - - $ref: '#/components/schemas/SetExpression' - - $ref: '#/components/schemas/LiteralExpression' + - $ref: '#/components/schemas/UnaryPredicate' + - $ref: '#/components/schemas/ComparisonPredicate' + - $ref: '#/components/schemas/SetPredicate' - $ref: '#/components/schemas/UnaryExpression' + - $ref: '#/components/schemas/LiteralExpression' + - $ref: '#/components/schemas/SetExpression' ExpressionType: type: string @@ -2561,7 +2565,22 @@ components: - "is-nan" - "not-nan" + ValueExpression: + description: > + A value expression per Iceberg Expressions spec, Appendix B: a literal, + a field reference, or a function application. The result type is + determined when the expression is bound to an input schema. + oneOf: + - $ref: '#/components/schemas/Literal' + - $ref: '#/components/schemas/FieldReference' + - $ref: '#/components/schemas/Apply' + TrueExpression: + deprecated: true + description: > + Deprecated. Use the bare boolean literal `true` as a predicate instead. + Retained for backward compatibility with older clients per the Iceberg + Expressions spec (Appendix B, JSON serialization). type: object required: - type @@ -2571,6 +2590,11 @@ components: const: "true" FalseExpression: + deprecated: true + description: > + Deprecated. Use the bare boolean literal `false` as a predicate instead. + Retained for backward compatibility with older clients per the Iceberg + Expressions spec (Appendix B, JSON serialization). type: object required: - type @@ -2606,7 +2630,207 @@ components: child: $ref: '#/components/schemas/Expression' + UnaryPredicate: + description: > + A predicate that tests a single value expression. Replaces the deprecated + UnaryExpression that used 'term'. + type: object + required: + - type + - child + properties: + type: + $ref: '#/components/schemas/ExpressionType' + enum: ["is-null", "not-null", "is-nan", "not-nan"] + child: + $ref: '#/components/schemas/ValueExpression' + + ComparisonPredicate: + description: > + A predicate that compares two value expressions. Replaces the deprecated + LiteralExpression that used 'term' and 'value'. + type: object + required: + - type + - left + - right + properties: + type: + $ref: '#/components/schemas/ExpressionType' + enum: ["lt", "lt-eq", "gt", "gt-eq", "eq", "not-eq", "starts-with", "not-starts-with"] + left: + $ref: '#/components/schemas/ValueExpression' + right: + $ref: '#/components/schemas/ValueExpression' + + SetPredicate: + description: > + A predicate that tests whether a value expression is in a set of literals. + Replaces the deprecated SetExpression that used 'term'. + type: object + required: + - type + - child + - values + properties: + type: + $ref: '#/components/schemas/ExpressionType' + enum: ["in", "not-in"] + child: + $ref: '#/components/schemas/ValueExpression' + values: + $ref: '#/components/schemas/Literals' + + Literal: + description: > + A literal value expression per Iceberg Expressions spec, Appendix B. + Three JSON forms are accepted: a bare scalar value, a typed literal + object without a data-type, or a typed literal object with an + explicit data-type. + oneOf: + - type: string + - type: number + - type: boolean + - type: object + additionalProperties: false + required: + - type + - value + properties: + type: + type: string + const: "literal" + value: + $ref: '#/components/schemas/PrimitiveTypeValue' + data-type: + $ref: '#/components/schemas/PrimitiveType' + + Literals: + description: > + A set of literal values per Iceberg Expressions spec, Appendix B. + Two JSON forms: a bare array of literals, or a typed object with an + explicit data-type applied to all values. + oneOf: + - type: array + items: + $ref: '#/components/schemas/Literal' + - type: object + additionalProperties: false + required: + - type + - values + - data-type + properties: + type: + type: string + const: "literals" + values: + type: array + items: + $ref: '#/components/schemas/PrimitiveTypeValue' + data-type: + $ref: '#/components/schemas/PrimitiveType' + + FieldReference: + description: > + A reference to a field per Iceberg Expressions spec, Appendix B. + Either a bound reference (by field ID) or an unbound reference (by + name). The context in which an expression is used determines which + form is valid. + oneOf: + - type: object + additionalProperties: false + required: + - type + - id + properties: + type: + type: string + const: "reference" + id: + type: integer + - type: object + additionalProperties: false + required: + - type + - name + properties: + type: + type: string + const: "reference" + name: + type: string + + Apply: + description: > + A function application per Iceberg Expressions spec, Appendix B. + Represents the result of calling a function on zero or more value + expressions or predicates. + type: object + additionalProperties: false + required: + - type + - function + - arguments + properties: + type: + type: string + const: "apply" + function: + $ref: '#/components/schemas/FunctionReference' + arguments: + type: array + items: + anyOf: + - $ref: '#/components/schemas/ValueExpression' + - $ref: '#/components/schemas/Expression' + + FunctionReference: + description: > + A reference to a function per Iceberg Expressions spec, Appendix B. + Four JSON forms: a bare name (single-part identifier), a list of + names (multi-part identifier), an object with an identifier, or an + object with both a catalog and an identifier. + oneOf: + - type: string + minLength: 1 + - type: array + minItems: 1 + items: + type: string + minLength: 1 + - type: object + additionalProperties: false + required: + - identifier + properties: + identifier: + type: array + minItems: 1 + items: + type: string + minLength: 1 + - type: object + additionalProperties: false + required: + - catalog + - identifier + properties: + catalog: + type: string + identifier: + type: array + minItems: 1 + items: + type: string + minLength: 1 + UnaryExpression: + deprecated: true + description: > + Deprecated. Use UnaryPredicate with 'child' (a ValueExpression) instead. + Retained for backward compatibility with older clients per the Iceberg + Expressions spec (Appendix B, Backward compatibility). type: object required: - type @@ -2619,6 +2843,11 @@ components: $ref: '#/components/schemas/Term' LiteralExpression: + deprecated: true + description: > + Deprecated. Use ComparisonPredicate with 'left' and 'right' (ValueExpressions) + instead. Retained for backward compatibility with older clients per the + Iceberg Expressions spec (Appendix B, Backward compatibility). type: object required: - type @@ -2631,9 +2860,14 @@ components: term: $ref: '#/components/schemas/Term' value: - $ref: '#/components/schemas/PrimitiveTypeValue' + $ref: '#/components/schemas/Literal' SetExpression: + deprecated: true + description: > + Deprecated. Use SetPredicate with 'child' (a ValueExpression) instead. + Retained for backward compatibility with older clients per the Iceberg + Expressions spec (Appendix B, Backward compatibility). type: object required: - type @@ -2646,20 +2880,37 @@ components: term: $ref: '#/components/schemas/Term' values: - type: array - items: - $ref: '#/components/schemas/PrimitiveTypeValue' + $ref: '#/components/schemas/Literals' Term: oneOf: - $ref: '#/components/schemas/Reference' - $ref: '#/components/schemas/TransformTerm' + - $ref: '#/components/schemas/DeprecatedReference' Reference: type: string example: - "column-name" + DeprecatedReference: + deprecated: true + description: > + Deprecated backward-compatibility form of a field reference used in + older REST predicates. Use FieldReference instead per Iceberg + Expressions spec, Appendix B (Backward compatibility). + type: object + additionalProperties: false + required: + - type + - term + properties: + type: + type: string + const: "reference" + term: + type: string + TransformTerm: type: object required: @@ -2673,7 +2924,7 @@ components: transform: $ref: '#/components/schemas/Transform' term: - $ref: '#/components/schemas/Reference' + $ref: '#/components/schemas/Term' Transform: type: string