Skip to content

feat(core)!: support nested map expressions and import nested structs - #1062

Open
nielspardon wants to merge 1 commit into
mainfrom
feat/core-nested-map-expressions
Open

feat(core)!: support nested map expressions and import nested structs#1062
nielspardon wants to merge 1 commit into
mainfrom
feat/core-nested-map-expressions

Conversation

@nielspardon

@nielspardon nielspardon commented Aug 5, 2026

Copy link
Copy Markdown
Member

Proto Expression.Nested has three arms — struct, list and map — but only list round-tripped. Expression.NestedMap did not exist at all, so the map arm was unreachable, and ProtoExpressionConverter.from(Nested) handled only case LIST: a plan carrying a nested struct failed on import with UnsupportedOperationException: Unimplemented nested type: STRUCT, even though the POJO to proto direction emitted one. (VirtualTableScan rows were unaffected — they use the separate from(Nested.Struct) overload.)

This adds the NestedMap POJO with the usual visitor and converter wiring, and imports all three nested kinds on the way back from proto.

Two details worth calling out:

  • Key order is part of the value. Proto Nested.Map is a repeated key_values, so NestedMap keeps insertion order — the Immutables-generated map is LinkedHashMap-backed — and both converters preserve it. Without that, a round trip could reorder the pairs.
  • @Value.Check throws rather than asserts. NestedList, written earlier, uses assert for the same invariants, which does not run outside a -ea JVM. NestedMap rejects an empty map (pointing at ExpressionCreator.emptyMap) and heterogeneous key or value types with IllegalArgumentException, matching the direction of Replace assert-based validation with real exceptions in :core and :isthmus #1047.

Isthmus still cannot convert nested structs or maps to and from Calcite; that follows in a stacked PR, which closes #375.

Part of #375

BREAKING CHANGE: ExpressionVisitor gains visit(Expression.NestedMap). Direct implementors must add it; implementors extending AbstractExpressionVisitor inherit the visitFallback default and need no change.

🤖 Generated with AI

Proto `Expression.Nested` has three arms — struct, list and map — but only
`list` round-tripped. `Expression.NestedMap` did not exist at all, so the
`map` arm was unreachable, and `ProtoExpressionConverter.from(Nested)`
handled only `case LIST`: a plan carrying a nested struct failed on import
with `UnsupportedOperationException: Unimplemented nested type: STRUCT`,
even though the POJO to proto direction emitted one. (`VirtualTableScan`
rows were unaffected — they use the separate `from(Nested.Struct)` overload.)

Adds the `NestedMap` POJO with the usual visitor and converter wiring, and
imports all three nested kinds on the way back from proto. `NestedMap`
preserves key-value order, so proto `key_values` ordering survives a round
trip, and its `@Value.Check` rejects an empty map and heterogeneous key or
value types with `IllegalArgumentException`.

Isthmus still cannot convert nested structs or maps to and from Calcite;
that follows separately.

Part of #375

BREAKING CHANGE: `ExpressionVisitor` gains `visit(Expression.NestedMap)`.
Direct implementors must add it; implementors extending
`AbstractExpressionVisitor` inherit the `visitFallback` default and need no
change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support for Nested expressions

1 participant