Skip to content

feat(core): add TopNRel physical operator#1007

Draft
nielspardon wants to merge 1 commit into
substrait-io:mainfrom
nielspardon:feat/topn-rel-core
Draft

feat(core): add TopNRel physical operator#1007
nielspardon wants to merge 1 commit into
substrait-io:mainfrom
nielspardon:feat/topn-rel-core

Conversation

@nielspardon

Copy link
Copy Markdown
Member

What

Adds core support for the TopNRel physical relational operator, introduced to the
Substrait spec in substrait#1009
and released in v0.88.0 (the spec version this repo's submodule pins). TopNRel
is a combined sort + fetch operator (top_n = 23 in the Rel oneof) — a genuinely new
relation rather than sugar over the existing Sort + Fetch, since it uses
Expression-based offset/count and adds WITH TIES semantics.

Changes

  • New POJO io.substrait.relation.physical.TopN (a SingleInputRel): >= 1 sort
    fields, Optional<Expression> offset (null → 0) and count (absent → ALL), and a nested
    Mode enum (UNSPECIFIED / ROWS_ONLY / WITH_TIES, default ROWS_ONLY) that maps
    to/from the proto FetchMode via toProto() / fromProto() — following the existing
    Set.SetOp pattern.
  • Relation visitor wiring: RelVisitor.visit(TopN), an AbstractRelVisitor fallback
    default, and RelCopyOnWriteVisitor.visit(TopN).
  • Both proto converters: RelProtoConverter (POJO → proto) and ProtoRelConverter
    (proto → POJO, including the TOP_N dispatch case).
  • DSL helper SubstraitBuilder.topN(...) for ergonomics.
  • Proto round-trip test TopNRelRoundtripTest covering rows-only, offset+count,
    count-absent (ALL), WITH_TIES, default mode, multiple sort fields, and nesting.

Scope

Engine mappings for isthmus (Calcite) and Spark are intentionally out of scope:
those integrations map only logical operators today, and neither engine has a native
single top-N node or WITH TIES semantics, so how to map this physical operator there is a
separate decision left for a follow-up. To keep the two direct RelVisitor implementors
outside :core compiling, SqlKindFromRel returns SELECT for TopN and the example
SubstraitStringify gains a stringify branch — no behavioral engine mapping is added.

Testing

./gradlew clean build passes: :core (PMD, javadoc, spotless, tests incl. the new
round-trip test), :isthmus, :examples:substrait-spark, and all three Spark variants
(spark-3.4_2.12, spark-3.5_2.12, spark-4.0_2.13).

Closes #806

🤖 Generated with AI

Add a TopN POJO (a SingleInputRel) modeling the TopNRel physical relation introduced in the Substrait spec v0.88.0: expression-based offset/count, a tie-handling mode (ROWS_ONLY/WITH_TIES), and one or more sort fields. Map the mode to/from the proto FetchMode enum, wire the relation visitor (RelVisitor, AbstractRelVisitor, RelCopyOnWriteVisitor), add both proto converters (RelProtoConverter and ProtoRelConverter), a SubstraitBuilder DSL helper, and a proto round-trip test.

Engine mappings for isthmus (Calcite) and Spark are intentionally out of scope: those integrations map only logical operators today, so how to map this physical operator is deferred. SqlKindFromRel and the example SubstraitStringify get the minimal visit(TopN) needed to keep the direct RelVisitor implementors compiling.

Closes substrait-io#806
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 TopNRel physical operator

1 participant