You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by si...@apache.org on 2026/07/27 18:52:13 UTC
(iceberg) branch main updated: OpenAPI: Update REST spec expressions to match new expressions spec (#17138)
This is an automated email from the ASF dual-hosted git repository.
singhpk234 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/main by this push:
new 832941eae9 OpenAPI: Update REST spec expressions to match new expressions spec (#17138)
832941eae9 is described below
commit 832941eae9e9e25269dcc84283b0e11e28bf188b
Author: Prashant Singh <35...@users.noreply.github.com>
AuthorDate: Mon Jul 27 11:52:08 2026 -0700
OpenAPI: Update REST spec expressions to match new expressions spec (#17138)
* OpenAPI: Update REST spec expressions to match new expressions spec
Adds UnaryPredicate, ComparisonPredicate, and SetPredicate schemas that
use 'child' and 'left'/'right' value expression references, matching
the JSON serialization defined in Appendix B of the Iceberg Expressions
spec (format/expressions-spec.md).
The existing UnaryExpression, LiteralExpression, and SetExpression
schemas (which use 'term'/'value'/'values') are marked deprecated but
retained in Expression.oneOf for backward compatibility with older
clients per the spec's "Backward compatibility" section.
A ValueExpression placeholder schema is added and referenced by the new
predicates; concrete LITERAL/REFERENCE/APPLY forms will be added in a
follow-up change.
* OpenAPI: Support bare boolean predicate form in REST expressions
Extends Expression.oneOf with a bare `boolean` alternative, matching the
spec-conformant PREDICATE production in the Iceberg Expressions spec
(format/expressions-spec.md, Appendix B) which defines `PREDICATE: true
| false | { ... }`.
The pre-existing TrueExpression and FalseExpression object-form schemas
(`{"type": "true"}` / `{"type": "false"}`) are marked deprecated and
retained in Expression.oneOf for backward compatibility with older
clients that send the object form.
* OpenAPI: Add ValueExpression schemas per Iceberg Expressions spec Appendix B
Replaces the ValueExpression placeholder with concrete oneOf schemas for
LITERAL, REFERENCE, and APPLY forms, matching Appendix B of the Iceberg
Expressions spec. Also adds the deprecated reference form for backward
compatibility with older REST predicates.
Schemas added:
- Literal (bare scalar, typed literal object with/without data-type)
- Literals (bare array or typed object; used by SetPredicate.values)
- FieldReference (bound by id or unbound by name)
- Apply (function application over ValueExpression or Expression args)
- FunctionReference (four forms: name, name list, identifier object,
catalog + identifier object)
- DeprecatedReference (backward-compat form wired into Term's oneOf)
SetPredicate.values now references Literals rather than an array of
ValueExpression to match Appendix B's LITERALS grammar.
* OpenAPI: Regenerate rest-catalog-open-api.py
* OpenAPI: Tighten ValueExpression schemas for Appendix B correctness
Apply spec-mandated fixes surfaced by adversarial review against
format/expressions-spec.md Appendix B:
- Literal.oneOf: remove the type:integer branch — every integer already
matches type:number, so the duplicate broke strict oneOf validators.
- Apply.arguments.items: switch oneOf to anyOf. Spec line 265 defines
FUNC_ARG as EXPR | PREDICATE (semantic "or"), and a bare boolean
legitimately matches both branches; oneOf's "exactly one" rejects it.
- FieldReference and DeprecatedReference: add additionalProperties:false
so the shared type:"reference" discriminator resolves to exactly one
branch. Without it, payloads mixing id/name/term validate ambiguously.
- Literals typed-object form: mark data-type required per spec line 258
grammar (it appears with no optional marker).
- FunctionReference: add additionalProperties:false to the {identifier}
form so it is disjoint from the {catalog, identifier} form (spec lines
267-269 enumerate them as distinct productions). Add minItems:1 to
every identifier array per spec line 82: "At least one part, the
function name, is required."
* OpenAPI: Regenerate rest-catalog-open-api.py
* OpenAPI: Further tighten ValueExpression schemas per adversarial review
Additional spec-fidelity fixes surfaced by iterated compliance/divergence
review against format/expressions-spec.md Appendix B:
- Literal typed-object, Literals typed-object, Apply, and FunctionReference
{catalog, identifier} all get additionalProperties:false so their JSON
shapes match the closed grammar productions in spec lines 255-269.
- LiteralExpression.value now refs Literal (was PrimitiveTypeValue) — spec
line 304 explicitly says the deprecated CMP_OP form takes LITERAL.
- SetExpression.values now refs Literals (was inline PrimitiveTypeValue
array) — spec line 305 says LITERALS, which includes bare-array and
typed-object forms.
- TransformTerm.term now refs Term (was Reference) — spec line 310 has
term:TERM, which is recursive and admits nested TRANSFORM and
DEPRECATED_REF, not only bare NAMEs.
- Literal bare oneOf drops type:'null' — Iceberg VALUE grammar (spec 254,
274) is a single scalar value; the typed form's PrimitiveTypeValue has
no null branch either, so the null form was asymmetric and dead-weight.
- FunctionReference NAME strings (bare-string form and identifier array
items across both object forms) get minLength:1 — spec line 82 requires
the function name to be a real identifier, not empty.
* OpenAPI: Regenerate rest-catalog-open-api.py
* OpenAPI: Address reviewer feedback on ValueExpression schemas
Adopt Nevin's review comments in narrower form:
- Strip "Replaces the deprecated X" clauses from UnaryPredicate,
ComparisonPredicate, and SetPredicate descriptions
- Rewrite SetPredicate description in operand-neutral form:
"A predicate that operates on a list of literals"
- Rename Literals from "set of literal values" to "list of literal
values" to match wire form (arrays are ordered, admit duplicates)
- Dedupe "Iceberg Expressions spec, Appendix B" citations across
Literal, Literals, FieldReference, Apply, and FunctionReference;
keep the citation on ValueExpression as the parent anchor
- Split FieldReference into named FieldReferenceById and
FieldReferenceByName joined via oneOf, preserving the
bound-vs-unbound context clause in the parent description
* OpenAPI: Regenerate rest-catalog-open-api.py
* OpenAPI: Tighten predicate/literal schemas per second-round review
- Add additionalProperties: false to UnaryPredicate, ComparisonPredicate,
and SetPredicate. Without this, a payload carrying both a new field
(e.g. child) and a legacy field (e.g. term) matches both the new
predicate and its deprecated counterpart under Expression.oneOf,
which is a validation error. Matches the pattern already applied to
Literal, FieldReference*, and Apply.
- Replace the bare-value Literal branch (string | number | boolean) with
a $ref to PrimitiveTypeValue. Per the expressions spec, VALUE is a
single value JSON drawn from the table spec's primitive types, which
includes dates, decimals, UUIDs, and other types the previous three-
primitive union excluded.
- Rewrite Literal, Literals, and FunctionReference descriptions using
the "X is either A, B, C" convention for consistency across the
expression schemas.
* OpenAPI: Regenerate rest-catalog-open-api.py
* OpenAPI: Consolidate predicate schemas per Ryan's feedback
Merge deprecated UnaryExpression, LiteralExpression, and SetExpression
into UnaryPredicate, ComparisonPredicate, and SetPredicate by adding
optional deprecated 'term'/'value' fields. Rename Expression to
Predicate, extract FunctionArgument and FunctionIdentifier types,
rename FieldReferenceById/ByName to IdReference/NamedReference, and
remove DeprecatedReference (never produced by implementations).
* OpenAPI: Complete naming pass per Ryan's feedback
Rename AndOrExpression/NotExpression to AndOrPredicate/NotPredicate
for consistency with the Predicate top-level schema. Rename
FieldReference to Reference (the new structured oneOf) and rename
the old bare-string Reference to TermReference (deprecated), matching
Ryan's stated preference for the prestigious name on the new type.
* OpenAPI: Inline function reference and reuse CatalogObjectIdentifier
Delete the FunctionReference and FunctionIdentifier wrapper schemas
(each was used only once) and inline the function oneOf directly
into Apply.function. Reuse the existing CatalogObjectIdentifier for
identifier arrays instead of redefining them inline, per Ryan's
narrow ask on the two identifier fields.
* OpenAPI: Drop Appendix B references from deprecation notices
Apply Ryan's principle ("this is its own spec definition") to the
TrueExpression and FalseExpression deprecation descriptions, removing
the Appendix B / JSON serialization references.
* OpenAPI: Restrict TransformTerm.term to TermReference
Per Ryan's feedback, TransformTerm.term should be a direct name
reference rather than a recursive Term union, so a transform can no
longer wrap another transform.
* OpenAPI: Mark legacy term types as deprecated
Per Ryan's feedback, deprecate the legacy term types consistently so
they are not reused: Term and TransformTerm now carry deprecated: true
alongside TermReference.
* OpenAPI: Allow Apply.function identifier object without catalog
The expressions spec permits a FUNC_REF of the form { "identifier":
[ NAME* ] } where catalog is missing/null. Make catalog optional on
the object variant of Apply.function so this form is representable.
---------
Co-authored-by: Prashant Singh <pr...@snowflake.com>
---
open-api/rest-catalog-open-api.py | 322 ++++++++++++++++++++++++++++--------
open-api/rest-catalog-open-api.yaml | 222 ++++++++++++++++++++++---
2 files changed, 444 insertions(+), 100 deletions(-)
diff --git a/open-api/rest-catalog-open-api.py b/open-api/rest-catalog-open-api.py
index cb0ec1dcb5..de95134766 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.
+
+ """
+
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.
+
+ """
+
type: Literal['false'] = Field(
...,
examples=[
@@ -209,8 +219,49 @@ class FalseExpression(BaseModel):
)
-class Reference(RootModel[str]):
- root: str = Field(..., examples=[['column-name']])
+class IdReference(BaseModel):
+ """
+ A bound reference to a field by field ID.
+ """
+
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal['reference']
+ id: int
+
+
+class NamedReference(BaseModel):
+ """
+ An unbound reference to a field by name.
+ """
+
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal['reference']
+ name: str
+
+
+class Function(RootModel[str]):
+ root: str = Field(..., min_length=1)
+
+
+class Function1(BaseModel):
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ catalog: str | None = None
+ identifier: CatalogObjectIdentifier
+
+
+class TermReference(RootModel[str]):
+ root: str = Field(
+ ...,
+ deprecated=True,
+ description='Deprecated string-form field reference used in older REST predicates. Use Reference (IdReference or NamedReference) instead.\n',
+ examples=[['column-name']],
+ )
class Transform(RootModel[str]):
@@ -1134,10 +1185,64 @@ class RenameTableRequest(BaseModel):
destination: TableIdentifier
+class Literal1(BaseModel):
+ """
+ A literal is either a bare value, an untyped literal object, or a typed literal object.
+
+ """
+
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal['literal']
+ value: PrimitiveTypeValue
+ data_type: PrimitiveType | None = Field(None, alias='data-type')
+
+
+class LiteralModel(RootModel[PrimitiveTypeValue | Literal1]):
+ root: PrimitiveTypeValue | Literal1 = Field(
+ ...,
+ description='A literal is either a bare value, an untyped literal object, or a typed literal object.\n',
+ )
+
+
+class Literals1(BaseModel):
+ """
+ Literals is either 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='Literals is either a bare array of literals or a typed object with an explicit data-type applied to all values.\n',
+ )
+
+
+class Reference(RootModel[IdReference | NamedReference]):
+ root: IdReference | NamedReference = Field(
+ ...,
+ description='A reference to a field. 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 TransformTerm(BaseModel):
+ """
+ Deprecated. Legacy transform-applied-to-a-term form. Use Apply with a Reference argument instead.
+
+ """
+
type: Literal['transform']
transform: Transform
- term: Reference
+ term: TermReference
class SetPartitionStatisticsUpdate(BaseUpdate):
@@ -1246,8 +1351,12 @@ class FetchScanTasksRequest(BaseModel):
plan_task: PlanTask = Field(..., alias='plan-task')
-class Term(RootModel[Reference | TransformTerm]):
- root: Reference | TransformTerm
+class Term(RootModel[TermReference | TransformTerm]):
+ root: TermReference | TransformTerm = Field(
+ ...,
+ deprecated=True,
+ description='Deprecated. Legacy term form used by older REST predicates. Use Reference or Apply instead.\n',
+ )
class SetStatisticsUpdate(BaseUpdate):
@@ -1285,8 +1394,39 @@ class FunctionDefinitionVersion(BaseModel):
)
-class UnaryExpression(BaseModel):
- type: Literal['is-null', 'not-null', 'is-nan', 'not-nan'] = Field(
+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 AndOrPredicate(BaseModel):
+ type: Literal['and', 'or'] = Field(
...,
examples=[
[
@@ -1312,13 +1452,12 @@ class UnaryExpression(BaseModel):
]
],
)
- term: Term
+ left: Predicate
+ right: Predicate
-class LiteralExpression(BaseModel):
- type: Literal[
- 'lt', 'lt-eq', 'gt', 'gt-eq', 'eq', 'not-eq', 'starts-with', 'not-starts-with'
- ] = Field(
+class NotPredicate(BaseModel):
+ type: Literal['not'] = Field(
...,
examples=[
[
@@ -1344,12 +1483,19 @@ class LiteralExpression(BaseModel):
]
],
)
- term: Term
- value: PrimitiveTypeValue
+ child: Predicate
-class SetExpression(BaseModel):
- type: Literal['in', 'not-in'] = Field(
+class UnaryPredicate(BaseModel):
+ """
+ A predicate that tests a single value expression. Accepts either 'child' (preferred) or 'term' (deprecated) to identify the operand.
+
+ """
+
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal['is-null', 'not-null', 'is-nan', 'not-nan'] = Field(
...,
examples=[
[
@@ -1375,43 +1521,24 @@ class SetExpression(BaseModel):
]
],
)
- term: Term
- values: list[PrimitiveTypeValue]
-
-
-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')
+ child: ValueExpression | None = None
+ term: Term | None = Field(
+ None, deprecated=True, description="Deprecated. Use 'child' instead."
+ )
-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 ComparisonPredicate(BaseModel):
+ """
+ A predicate that compares two value expressions. Accepts either 'left'/'right' (preferred) or 'term'/'value' (deprecated).
+ """
-class AndOrExpression(BaseModel):
- type: Literal['and', 'or'] = Field(
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal[
+ 'lt', 'lt-eq', 'gt', 'gt-eq', 'eq', 'not-eq', 'starts-with', 'not-starts-with'
+ ] = Field(
...,
examples=[
[
@@ -1437,12 +1564,26 @@ class AndOrExpression(BaseModel):
]
],
)
- left: Expression
- right: Expression
+ left: ValueExpression | None = None
+ right: ValueExpression | None = None
+ term: Term | None = Field(
+ None, deprecated=True, description="Deprecated. Use 'left' instead."
+ )
+ value: LiteralModel | None = Field(
+ None, deprecated=True, description="Deprecated. Use 'right' instead."
+ )
-class NotExpression(BaseModel):
- type: Literal['not'] = Field(
+class SetPredicate(BaseModel):
+ """
+ A predicate that tests whether a value is in a set of literals. Accepts either 'child' (preferred) or 'term' (deprecated) to identify the operand.
+
+ """
+
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal['in', 'not-in'] = Field(
...,
examples=[
[
@@ -1468,7 +1609,25 @@ class NotExpression(BaseModel):
]
],
)
- child: Expression
+ child: ValueExpression | None = None
+ term: Term | None = Field(
+ None, deprecated=True, description="Deprecated. Use 'child' instead."
+ )
+ values: Literals
+
+
+class Apply(BaseModel):
+ """
+ A function application on zero or more value expressions or predicates.
+
+ """
+
+ model_config = ConfigDict(
+ extra='forbid',
+ )
+ type: Literal['apply']
+ function: Function | CatalogObjectIdentifier | Function1
+ arguments: list[FunctionArgument]
class TableMetadata(BaseModel):
@@ -1695,7 +1854,7 @@ class LoadViewResult(BaseModel):
class ScanReport(BaseModel):
table_name: str = Field(..., alias='table-name')
snapshot_id: int = Field(..., alias='snapshot-id')
- filter: Expression
+ filter: Predicate
schema_id: int = Field(..., alias='schema-id')
projected_field_ids: list[int] = Field(..., alias='projected-field-ids')
projected_field_names: list[str] = Field(..., alias='projected-field-names')
@@ -1847,8 +2006,8 @@ class PlanTableScanRequest(BaseModel):
select: list[FieldName] | None = Field(
None, description='List of selected schema fields'
)
- filter: Expression | None = Field(
- None, description='Expression used to filter the table data'
+ filter: Predicate | None = Field(
+ None, description='Predicate used to filter the table data'
)
min_rows_requested: int | None = Field(
None,
@@ -1889,7 +2048,7 @@ class FileScanTask(BaseModel):
alias='delete-file-references',
description='A list of indices in the delete files array (0-based)',
)
- residual_filter: Expression | None = Field(
+ residual_filter: Predicate | None = Field(
None,
alias='residual-filter',
description='An optional filter to be applied to rows in this file scan task.\nIf the residual is not present, the client must produce the residual or use the original filter.',
@@ -1905,25 +2064,34 @@ class Type(RootModel[PrimitiveType | StructType | ListType | MapType]):
root: PrimitiveType | StructType | ListType | MapType
-class Expression(
+class Predicate(
RootModel[
- TrueExpression
+ bool
+ | TrueExpression
| FalseExpression
- | AndOrExpression
- | NotExpression
- | SetExpression
- | LiteralExpression
- | UnaryExpression
+ | AndOrPredicate
+ | NotPredicate
+ | UnaryPredicate
+ | ComparisonPredicate
+ | SetPredicate
]
):
root: (
- TrueExpression
+ bool
+ | TrueExpression
| FalseExpression
- | AndOrExpression
- | NotExpression
- | SetExpression
- | LiteralExpression
- | UnaryExpression
+ | AndOrPredicate
+ | NotPredicate
+ | UnaryPredicate
+ | ComparisonPredicate
+ | SetPredicate
+ )
+
+
+class ValueExpression(RootModel[LiteralModel | Reference | Apply]):
+ root: LiteralModel | Reference | Apply = Field(
+ ...,
+ description='A value expression: a literal, a field reference, or a function application.\n',
)
@@ -2039,6 +2207,10 @@ class FunctionDataType(
)
+class FunctionArgument(RootModel[ValueExpression | Predicate]):
+ root: ValueExpression | Predicate
+
+
class CompletedPlanningWithIDResult(CompletedPlanningResult):
plan_id: str = Field(
..., alias='plan-id', description='ID used to track a planning request'
@@ -2083,8 +2255,12 @@ class PlanTableScanResult(
StructField.model_rebuild()
ListType.model_rebuild()
MapType.model_rebuild()
-AndOrExpression.model_rebuild()
-NotExpression.model_rebuild()
+AndOrPredicate.model_rebuild()
+NotPredicate.model_rebuild()
+UnaryPredicate.model_rebuild()
+ComparisonPredicate.model_rebuild()
+SetPredicate.model_rebuild()
+Apply.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 997e08f4cc..dfa97292d0 100644
--- a/open-api/rest-catalog-open-api.yaml
+++ b/open-api/rest-catalog-open-api.yaml
@@ -2528,15 +2528,16 @@ components:
items:
type: integer
- Expression:
+ Predicate:
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/UnaryExpression'
+ - $ref: '#/components/schemas/AndOrPredicate'
+ - $ref: '#/components/schemas/NotPredicate'
+ - $ref: '#/components/schemas/UnaryPredicate'
+ - $ref: '#/components/schemas/ComparisonPredicate'
+ - $ref: '#/components/schemas/SetPredicate'
ExpressionType:
type: string
@@ -2561,7 +2562,18 @@ components:
- "is-nan"
- "not-nan"
+ ValueExpression:
+ description: >
+ A value expression: a literal, a field reference, or a function application.
+ oneOf:
+ - $ref: '#/components/schemas/Literal'
+ - $ref: '#/components/schemas/Reference'
+ - $ref: '#/components/schemas/Apply'
+
TrueExpression:
+ deprecated: true
+ description: >
+ Deprecated. Use the bare boolean literal `true` as a predicate instead.
type: object
required:
- type
@@ -2571,6 +2583,9 @@ components:
const: "true"
FalseExpression:
+ deprecated: true
+ description: >
+ Deprecated. Use the bare boolean literal `false` as a predicate instead.
type: object
required:
- type
@@ -2579,7 +2594,7 @@ components:
$ref: '#/components/schemas/ExpressionType'
const: "false"
- AndOrExpression:
+ AndOrPredicate:
type: object
required:
- type
@@ -2590,11 +2605,11 @@ components:
$ref: '#/components/schemas/ExpressionType'
enum: ["and", "or"]
left:
- $ref: '#/components/schemas/Expression'
+ $ref: '#/components/schemas/Predicate'
right:
- $ref: '#/components/schemas/Expression'
+ $ref: '#/components/schemas/Predicate'
- NotExpression:
+ NotPredicate:
type: object
required:
- type
@@ -2604,63 +2619,216 @@ components:
$ref: '#/components/schemas/ExpressionType'
const: "not"
child:
- $ref: '#/components/schemas/Expression'
+ $ref: '#/components/schemas/Predicate'
- UnaryExpression:
+ UnaryPredicate:
+ description: >
+ A predicate that tests a single value expression. Accepts either
+ 'child' (preferred) or 'term' (deprecated) to identify the operand.
type: object
+ additionalProperties: false
required:
- type
- - term
properties:
type:
$ref: '#/components/schemas/ExpressionType'
enum: ["is-null", "not-null", "is-nan", "not-nan"]
+ child:
+ $ref: '#/components/schemas/ValueExpression'
term:
+ deprecated: true
+ description: "Deprecated. Use 'child' instead."
$ref: '#/components/schemas/Term'
- LiteralExpression:
+ ComparisonPredicate:
+ description: >
+ A predicate that compares two value expressions. Accepts either
+ 'left'/'right' (preferred) or 'term'/'value' (deprecated).
type: object
+ additionalProperties: false
required:
- type
- - term
- - value
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'
term:
+ deprecated: true
+ description: "Deprecated. Use 'left' instead."
$ref: '#/components/schemas/Term'
value:
- $ref: '#/components/schemas/PrimitiveTypeValue'
+ deprecated: true
+ description: "Deprecated. Use 'right' instead."
+ $ref: '#/components/schemas/Literal'
- SetExpression:
+ SetPredicate:
+ description: >
+ A predicate that tests whether a value is in a set of literals. Accepts
+ either 'child' (preferred) or 'term' (deprecated) to identify the operand.
type: object
+ additionalProperties: false
required:
- type
- - term
- values
properties:
type:
$ref: '#/components/schemas/ExpressionType'
enum: ["in", "not-in"]
+ child:
+ $ref: '#/components/schemas/ValueExpression'
term:
+ deprecated: true
+ description: "Deprecated. Use 'child' instead."
$ref: '#/components/schemas/Term'
values:
+ $ref: '#/components/schemas/Literals'
+
+ Literal:
+ description: >
+ A literal is either a bare value, an untyped literal object, or a
+ typed literal object.
+ oneOf:
+ - $ref: '#/components/schemas/PrimitiveTypeValue'
+ - 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: >
+ Literals is either 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'
+
+ Reference:
+ description: >
+ A reference to a field. 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:
+ - $ref: '#/components/schemas/IdReference'
+ - $ref: '#/components/schemas/NamedReference'
+
+ IdReference:
+ description: A bound reference to a field by field ID.
+ type: object
+ additionalProperties: false
+ required:
+ - type
+ - id
+ properties:
+ type:
+ type: string
+ const: "reference"
+ id:
+ type: integer
+
+ NamedReference:
+ description: An unbound reference to a field by name.
+ type: object
+ additionalProperties: false
+ required:
+ - type
+ - name
+ properties:
+ type:
+ type: string
+ const: "reference"
+ name:
+ type: string
+
+ Apply:
+ description: >
+ A function application on zero or more value expressions or predicates.
+ type: object
+ additionalProperties: false
+ required:
+ - type
+ - function
+ - arguments
+ properties:
+ type:
+ type: string
+ const: "apply"
+ function:
+ oneOf:
+ - type: string
+ minLength: 1
+ - $ref: '#/components/schemas/CatalogObjectIdentifier'
+ - type: object
+ additionalProperties: false
+ required:
+ - identifier
+ properties:
+ catalog:
+ type: string
+ identifier:
+ $ref: '#/components/schemas/CatalogObjectIdentifier'
+ arguments:
type: array
items:
- $ref: '#/components/schemas/PrimitiveTypeValue'
+ $ref: '#/components/schemas/FunctionArgument'
+
+ FunctionArgument:
+ anyOf:
+ - $ref: '#/components/schemas/ValueExpression'
+ - $ref: '#/components/schemas/Predicate'
Term:
+ deprecated: true
+ description: >
+ Deprecated. Legacy term form used by older REST predicates.
+ Use Reference or Apply instead.
oneOf:
- - $ref: '#/components/schemas/Reference'
+ - $ref: '#/components/schemas/TermReference'
- $ref: '#/components/schemas/TransformTerm'
- Reference:
+ TermReference:
+ deprecated: true
+ description: >
+ Deprecated string-form field reference used in older REST predicates.
+ Use Reference (IdReference or NamedReference) instead.
type: string
example:
- "column-name"
TransformTerm:
+ deprecated: true
+ description: >
+ Deprecated. Legacy transform-applied-to-a-term form.
+ Use Apply with a Reference argument instead.
type: object
required:
- type
@@ -2673,7 +2841,7 @@ components:
transform:
$ref: '#/components/schemas/Transform'
term:
- $ref: '#/components/schemas/Reference'
+ $ref: '#/components/schemas/TermReference'
Transform:
type: string
@@ -4251,7 +4419,7 @@ components:
type: integer
format: int64
filter:
- $ref: '#/components/schemas/Expression'
+ $ref: '#/components/schemas/Predicate'
schema-id:
type: integer
projected-field-ids:
@@ -5134,8 +5302,8 @@ components:
$ref: '#/components/schemas/FieldName'
filter:
description:
- Expression used to filter the table data
- $ref: '#/components/schemas/Expression'
+ Predicate used to filter the table data
+ $ref: '#/components/schemas/Predicate'
min-rows-requested:
description:
The minimum number of rows requested for the scan. This is used as a hint
@@ -5225,7 +5393,7 @@ components:
If the residual is not present, the client must produce the
residual or use the original filter.
allOf:
- - $ref: '#/components/schemas/Expression'
+ - $ref: '#/components/schemas/Predicate'
MultiValuedMap:
description: A map of string keys where each key can map to multiple string values.