Uh oh!
There was an error while loading. Please reload this page.
Core, Spark: Introduce shared MultiColumnTerm to de-duplicate Z-order and Hilbert clustering - #17893
Core, Spark: Introduce shared MultiColumnTerm to de-duplicate Z-order and Hilbert clustering#17893GGraziadei wants to merge 1 commit into
Conversation
… and Hilbert clustering
GGraziadei
commented
Aug 30, 2026
Please consider GGraziadei#1 as the natural follow-up once this PR is merged. The idea is to extend the grammar to natively support transformations, improving the quality of Z-order and Hilbert clustering. E.g. |
uros-b
left a comment
There was a problem hiding this comment.
This seems like a clean mechanical refactor, so thank you @GGraziadei - let's leave up to maintainters (@RussellSpitzer, @nssalian) to take this further
gimgit
commented
Sep 3, 2026
The de-duplication looks clean, and parameterising the per-curve error strings keeps the user-facing behavior stable. One place where the refactor changes the failure mode for future extension: in Minor: |
Closes#17657.
Follow-up to #16827, which deliberately mirrored the Z-order surface to keep that diff reviewable. This PR is the deferred de-duplication, along the lines @RussellSpitzer suggested in review ("we'll probably want a
MultiColumnTermor something like that in the future").What changed
Core — new
org.apache.iceberg.expressions.MultiColumnTerm, an immutableTermover an ordered list of column references.ZorderandHilbert(previously identical apart from the class name) become two-line subclasses. Public constructors andrefs()are unchanged; the parsed SQL grammar is untouched.Spark 4.1 —
SparkZOrderFileRewriteRunnerandSparkHilbertFileRewriteRunnermove onto a new abstractSparkCurveFileRewriteRunner, parameterised by the internal value column name, the exact per-curve error messages, and the combine step. The shared pieces — internal column schema/sort order, column validation (validZOrderColNames/validHilbertColNameswere byte-for-byte the same logic),sortSchema,sortedDF, and the per-column ordered-bytes conversion — now live in one place. Each runner keeps only what is genuinely curve-specific: Z-order its two options and the interleave combine (~120 lines), Hilbert its fixed per-column bit width and the Hilbert-index combine (~75 lines). Adding a further curve is now a small, local change.Dispatch — the duplicated
zorder/hilbertbranches inSpark3Util.toIcebergTermshare one reference-extraction helper, andRewriteDataFilesProcedurecollapses its two per-curve term lists into a singleList<MultiColumnTerm>(mixing curves is detected by distinct term classes; error messages unchanged).What did not change
Engine-side behaviour is bit-for-bit identical, which the existing tests enforce: every pre-existing Z-order and Hilbert test passes unmodified (
TestSparkFileRewriteRunners, the Z-order/Hilbert cases ofTestRewriteDataFilesAction,TestRewriteDataFilesProcedure). The only test change is the newTestMultiColumnTermin core. All user-facing error messages are preserved exactly. Spark 3.5/4.0 are untouched.Out of scope
The wider "arbitrary function via
Expressions" refactor discussed in #16827 review builds naturally on this abstraction but is split out per the issue, to keep this diff mechanical and easy to verify.