Type column names as ColumnName across the read path (keystone)#200
Merged
Conversation
…#200) A Map<String, Array> lies about its own domain: String admits any text, but the map holds columns of this schema. Typing the key — the keystone being DType.Struct.fieldNames() -> List<ColumnName> — makes the signature tell the truth and turns whole classes of key-mismatch bugs into compile errors (this change's own calcite zoneStats.get(col) NPE, a String-map looked up with a ColumnName, could no longer compile). Typed throughout vortex's own APIs: fieldNames(), VortexReader.columnStats() keys, RowFilter.Column.column, ScanIterator projection, the writer's internal column maps, and the Chunk.put(ColumnName) builder. The builder's former put(String) sugar was test-only, so it came off. String stays only at genuine external boundaries — user-input sugar (field(String), RowFilter.eq(String), ScanOptions.columns(String...), writeChunk(Map<String,Object>)) and other-system namespaces (Calcite RelDataType, CSV headers, JDBC/Parquet metadata) — converted via .value() at the seam. Wire output byte-identical; Rust-interop oracle green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 6, 2026
dfa1
added a commit
that referenced
this pull request
Jul 6, 2026
Follow-up to the writeChunk(Map<ColumnName, Object>) retype (#201) and the Chunk.put(ColumnName, ...) builder (#200): doc snippets still showed String keys and would not compile. DocsConsistencyTest is blind to them (the .put("x", ...) / writeChunk(Map<...>) forms have no dotted receiver its regex can match), so this was caught in review, not CI. - reference.md: writeChunk(Map<String, Object>) -> Map<ColumnName, Object> - README / tutorial / compatibility: .put("x", ...) -> .put(ColumnName.of("x"), ...) - tutorial: add the ColumnName import - JdbcImporter.toChunkMap: drop a pointless ColumnName -> String -> ColumnName round-trip (List<ColumnName> names = schema.fieldNames()) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dfa1
added a commit
that referenced
this pull request
Jul 6, 2026
The Chunk builder row still read put(String column, Object data) but the method has taken ColumnName since #200. A survey of backticked method-signature claims (prompted by the #202 review) surfaced it; #202 fixed the fenced .put snippets but missed this reference table row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Column names inside vortex are typed as
ColumnName, not rawString. The keystone isDType.Struct.fieldNames()→List<ColumnName>; from there the types flow through the whole read path.Why (the real reason — it's not "just validation")
A
Map<String, Array>lies about its own domain.Stringsays "any text at all"; the map actually holds columns of this schema. Narrowing it toMap<ColumnName, Array>makes the type tell the truth: this maps column names to columns — not arbitrary strings.That's the payoff, and it's structural:
zoneStats.get(col)— aMap<String>looked up with aColumnName— compiled (becauseMap.get(Object)erases the key type) and returnednullat runtime. With the key typed, that mismatch can't compile. A whole class of "wrong string in a lookup" bugs is now caught at the source.StructBuilder.field()already validated each name throughColumnName.of()— thenbuild()unwrapped it back toStringone line later. The invariant now survives instead of being thrown away.ColumnNameconstruction — a footgun-named schema can no longer be built, so the writer's redundant runtime guard is deleted.Typed downstream for free:
VortexReader.columnStats()keys,RowFilter.Column.column,ScanIterator's projection match, and the writer's internal column-keyed maps — each signature now says what it means.Boundary discipline
Types live inside; strings stay at the external world, which is correct — those are another system's namespace, not vortex column names:
structBuilder().field(String),RowFilter.eq(String, …),ScanOptions.columns(String...),writeChunk(Map<String,Object>)— validate at the edge.String, converting via.value()right at the boundary: CalciteRelDataTypenames, CSV headers, JDBC metadata, Parquet schemas, CLI/TUI rendered text.Verification
./mvnw verify— full, all 15 modules incl. the failsafe Rust-interop oracle. Wire output is byte-identical (the file still stores raw name strings), so the oracle passing is the proof this is behavior-preserving../mvnw javadoc:javadoc -pl corezero output;DocsConsistencyTestgreen.Public-API change (
fieldNames(),columnStats(),RowFilter.Column) —0.13.0-shaped; changelog updated.🤖 Generated with Claude Code