Skip to content

Commit 9621502

Browse files
dfa1claude
andcommitted
refactor(writer): Chunk builder put is ColumnName-only
The writer Chunk builder (put + writeChunk(Consumer)) is used only by tests — production import paths all go through writeChunk(Map<String,Object>). So put(String) was test-only sugar with no production ergonomics to protect; drop it and keep the typed put(ColumnName). The builder is vortex's own API, not an external namespace, so its column name is a ColumnName. writeChunk(Map<String,Object>) stays String-keyed — that one IS production (CSV/JDBC/Parquet importers) and its keys are external metadata names (ResultSetMetaData, Parquet MessageType), a true boundary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 08ab238 commit 9621502

5 files changed

Lines changed: 27 additions & 40 deletions

File tree

writer/src/main/java/io/github/dfa1/vortex/writer/Chunk.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,6 @@
2626
/// | Bool | `boolean[]` | `Boolean[]` |
2727
public interface Chunk {
2828

29-
/// Adds a column's data to the chunk, addressing it by raw name. The name is validated
30-
/// through [ColumnName#of(String)] before lookup.
31-
///
32-
/// @param column the column name; must exist in the writer's schema
33-
/// @param data the column data; type must match the schema (see class javadoc)
34-
/// @return this builder
35-
/// @throws IllegalArgumentException if `column` is not in the schema or
36-
/// `data` is of the wrong type for the column
37-
Chunk put(String column, Object data);
38-
3929
/// Adds a column's data to the chunk, addressing it by its validated [ColumnName].
4030
///
4131
/// @param column the column name; must exist in the writer's schema

writer/src/main/java/io/github/dfa1/vortex/writer/ChunkImpl.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@ final class ChunkImpl implements Chunk {
2020
this.schema = schema;
2121
}
2222

23-
@Override
24-
public Chunk put(String column, Object value) {
25-
return put(ColumnName.of(column), value);
26-
}
27-
2823
@Override
2924
public Chunk put(ColumnName column, Object value) {
3025
int idx = schema.fieldNames().indexOf(column);

writer/src/main/java/io/github/dfa1/vortex/writer/VortexWriter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,10 @@ private static ByteBuffer buildPostscript(
387387
///
388388
/// ```java
389389
/// writer.writeChunk(c -> c
390-
/// .put("timestamp", new long[] {1_700_000_000_000L, 1_700_000_001_000L})
391-
/// .put("symbol", new String[] {"AAPL", "AAPL"})
392-
/// .put("price", new double[] {189.95, 190.10})
393-
/// .put("volume", new Long[] {100L, null})); // boxed → nullable
390+
/// .put(ColumnName.of("timestamp"), new long[] {1_700_000_000_000L, 1_700_000_001_000L})
391+
/// .put(ColumnName.of("symbol"), new String[] {"AAPL", "AAPL"})
392+
/// .put(ColumnName.of("price"), new double[] {189.95, 190.10})
393+
/// .put(ColumnName.of("volume"), new Long[] {100L, null})); // boxed → nullable
394394
/// ```
395395
///
396396
/// @param builder consumer that populates a [Chunk] with all schema columns

writer/src/test/java/io/github/dfa1/vortex/writer/ChunkImplTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ private static DType prim(PType ptype, boolean nullable) {
2525

2626
private static Object putGet(DType dtype, Object value) {
2727
ChunkImpl sut = new ChunkImpl(schema(dtype));
28-
sut.put("c", value);
28+
sut.put(ColumnName.of("c"), value);
2929
return sut.finish().get("c");
3030
}
3131

@@ -38,18 +38,18 @@ void unknownColumnRejected() {
3838
ChunkImpl sut = new ChunkImpl(schema(prim(PType.I32, false)));
3939

4040
// When / Then
41-
assertThatThrownBy(() -> sut.put("nope", new int[]{1}))
41+
assertThatThrownBy(() -> sut.put(ColumnName.of("nope"), new int[]{1}))
4242
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("unknown column");
4343
}
4444

4545
@Test
4646
void duplicatePutRejected() {
4747
// Given
4848
ChunkImpl sut = new ChunkImpl(schema(prim(PType.I32, false)));
49-
sut.put("c", new int[]{1});
49+
sut.put(ColumnName.of("c"), new int[]{1});
5050

5151
// When / Then
52-
assertThatThrownBy(() -> sut.put("c", new int[]{2}))
52+
assertThatThrownBy(() -> sut.put(ColumnName.of("c"), new int[]{2}))
5353
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("duplicate");
5454
}
5555

@@ -59,7 +59,7 @@ void putReturnsSelfForChaining() {
5959
ChunkImpl sut = new ChunkImpl(schema(prim(PType.I32, false)));
6060

6161
// When
62-
Chunk result = sut.put("c", new int[]{1});
62+
Chunk result = sut.put(ColumnName.of("c"), new int[]{1});
6363

6464
// Then
6565
assertThat(result).isSameAs(sut);
@@ -70,7 +70,7 @@ void finishRejectsMissingColumn() {
7070
// Given — schema has two columns, only one put
7171
ChunkImpl sut = new ChunkImpl(new DType.Struct(
7272
List.of(ColumnName.of("a"), ColumnName.of("b")), List.of(prim(PType.I32, false), prim(PType.I32, false)), false));
73-
sut.put("a", new int[]{1});
73+
sut.put(ColumnName.of("a"), new int[]{1});
7474

7575
// When / Then
7676
assertThatThrownBy(sut::finish)
@@ -82,7 +82,7 @@ void finishReturnsAllColumns() {
8282
// Given
8383
ChunkImpl sut = new ChunkImpl(schema(prim(PType.I32, false)));
8484
int[] col = {1, 2, 3};
85-
sut.put("c", col);
85+
sut.put(ColumnName.of("c"), col);
8686

8787
// When
8888
Map<String, Object> result = sut.finish();

writer/src/test/java/io/github/dfa1/vortex/writer/TypedChunkBuilderTest.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.github.dfa1.vortex.writer;
22

3+
import io.github.dfa1.vortex.core.model.ColumnName;
4+
35
import io.github.dfa1.vortex.core.model.DType;
46
import io.github.dfa1.vortex.reader.ReadRegistry;
57
import io.github.dfa1.vortex.reader.VortexReader;
@@ -36,9 +38,9 @@ void writeChunk_typed_roundTrips(@TempDir Path tmp) throws IOException {
3638
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
3739
// When
3840
sut.writeChunk(c -> c
39-
.put("timestamp", new long[]{1_700_000_000_000L, 1_700_000_001_000L})
40-
.put("symbol", new String[]{"AAPL", "AAPL"})
41-
.put("price", new double[]{189.95, 190.10}));
41+
.put(ColumnName.of("timestamp"), new long[]{1_700_000_000_000L, 1_700_000_001_000L})
42+
.put(ColumnName.of("symbol"), new String[]{"AAPL", "AAPL"})
43+
.put(ColumnName.of("price"), new double[]{189.95, 190.10}));
4244
}
4345

4446
// Then — file is readable and values round-trip
@@ -58,7 +60,7 @@ void put_unknownColumn_throws(@TempDir Path tmp) throws IOException {
5860
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
5961
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
6062
// When / Then
61-
assertThatThrownBy(() -> sut.writeChunk(c -> c.put("nope", new long[]{1})))
63+
assertThatThrownBy(() -> sut.writeChunk(c -> c.put(ColumnName.of("nope"), new long[]{1})))
6264
.isInstanceOf(IllegalArgumentException.class)
6365
.hasMessageContaining("unknown column: nope");
6466
}
@@ -71,7 +73,7 @@ void put_wrongArrayType_throws(@TempDir Path tmp) throws IOException {
7173
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
7274
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
7375
// When / Then — int[] for I64 column
74-
assertThatThrownBy(() -> sut.writeChunk(c -> c.put("timestamp", new int[]{1, 2})))
76+
assertThatThrownBy(() -> sut.writeChunk(c -> c.put(ColumnName.of("timestamp"), new int[]{1, 2})))
7577
.isInstanceOf(IllegalArgumentException.class)
7678
.hasMessageContaining("timestamp")
7779
.hasMessageContaining("I64");
@@ -86,8 +88,8 @@ void missingColumn_throws_atClose(@TempDir Path tmp) throws IOException {
8688
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
8789
// When / Then
8890
assertThatThrownBy(() -> sut.writeChunk(c -> c
89-
.put("timestamp", new long[]{1L})
90-
.put("symbol", new String[]{"A"})))
91+
.put(ColumnName.of("timestamp"), new long[]{1L})
92+
.put(ColumnName.of("symbol"), new String[]{"A"})))
9193
.isInstanceOf(IllegalStateException.class)
9294
.hasMessageContaining("missing column: price");
9395
}
@@ -104,7 +106,7 @@ void nullable_i64Column_acceptsBoxedArrayWithNulls(@TempDir Path tmp) throws IOE
104106
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
105107
var sut = VortexWriter.create(ch, nullableSchema, WriteOptions.defaults())) {
106108
// When
107-
sut.writeChunk(c -> c.put("v", new Long[]{1L, null, 3L}));
109+
sut.writeChunk(c -> c.put(ColumnName.of("v"), new Long[]{1L, null, 3L}));
108110
}
109111

110112
// Then — file is well-formed; the masked encoding output is verified by the
@@ -119,7 +121,7 @@ void nonNullable_i64Column_rejectsBoxedArray(@TempDir Path tmp) throws IOExcepti
119121
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
120122
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
121123
// When / Then
122-
assertThatThrownBy(() -> sut.writeChunk(c -> c.put("timestamp", new Long[]{1L, 2L})))
124+
assertThatThrownBy(() -> sut.writeChunk(c -> c.put(ColumnName.of("timestamp"), new Long[]{1L, 2L})))
123125
.isInstanceOf(IllegalArgumentException.class)
124126
.hasMessageContaining("non-nullable")
125127
.hasMessageContaining("timestamp");
@@ -134,8 +136,8 @@ void duplicatePut_throws(@TempDir Path tmp) throws IOException {
134136
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
135137
// When / Then
136138
assertThatThrownBy(() -> sut.writeChunk(c -> c
137-
.put("timestamp", new long[]{1L})
138-
.put("timestamp", new long[]{2L})))
139+
.put(ColumnName.of("timestamp"), new long[]{1L})
140+
.put(ColumnName.of("timestamp"), new long[]{2L})))
139141
.isInstanceOf(IllegalArgumentException.class)
140142
.hasMessageContaining("duplicate")
141143
.hasMessageContaining("timestamp");
@@ -150,9 +152,9 @@ void columnLengthMismatch_throws(@TempDir Path tmp) throws IOException {
150152
var sut = VortexWriter.create(ch, SCHEMA, WriteOptions.defaults())) {
151153
// When / Then — timestamp has 2 rows, symbol has 3, price has 2
152154
assertThatThrownBy(() -> sut.writeChunk(c -> c
153-
.put("timestamp", new long[]{1L, 2L})
154-
.put("symbol", new String[]{"A", "B", "C"})
155-
.put("price", new double[]{1.0, 2.0})))
155+
.put(ColumnName.of("timestamp"), new long[]{1L, 2L})
156+
.put(ColumnName.of("symbol"), new String[]{"A", "B", "C"})
157+
.put(ColumnName.of("price"), new double[]{1.0, 2.0})))
156158
.isInstanceOf(IllegalArgumentException.class)
157159
.hasMessageContaining("symbol")
158160
.hasMessageContaining("3 rows")

0 commit comments

Comments
 (0)