Skip to content

Commit 19d9de3

Browse files
rustyconoverclaude
andauthored
fix: Pass explicit length in Struct makeData calls (#404)
## Summary - Pass `length: data.length` in `setChildAt` to preserve the batch's row count when constructing Struct data - Pass `length: 0` explicitly in `_InternalEmptyPlaceholderRecordBatch` instead of relying on reduce-over-children fallback - Add tests for Struct `makeData` with empty children and `setChildAt` row count preservation Closes #403 ## Test plan - [x] `makeData` with empty children preserves explicit length - [x] `makeData` with empty children and no length defaults to 0 - [x] `setChildAt` preserves `numRows` after column replacement - [x] Full test suite passes (`yarn test -t src`) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 521207e commit 19d9de3

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

src/recordbatch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ export class RecordBatch<T extends TypeMap = any> {
261261
const field = fields[index].clone({ type: child.type });
262262
[fields[index], children[index]] = [field, child.data[0]];
263263
schema = new Schema(fields, new Map(this.schema.metadata));
264-
data = makeData({ type: new Struct<T>(fields), children });
264+
data = makeData({ type: new Struct<T>(fields), length: data.length, children });
265265
}
266266
return new RecordBatch(schema, data, this._metadata);
267267
}
@@ -380,7 +380,7 @@ function collectDictionaries(fields: Field[], children: readonly Data[], diction
380380
export class _InternalEmptyPlaceholderRecordBatch<T extends TypeMap = any> extends RecordBatch<T> {
381381
constructor(schema: Schema<T>, metadata?: Map<string, string>) {
382382
const children = schema.fields.map((f) => makeData({ type: f.type }));
383-
const data = makeData({ type: new Struct<T>(schema.fields), nullCount: 0, children });
383+
const data = makeData({ type: new Struct<T>(schema.fields), length: 0, nullCount: 0, children });
384384
super(schema, data, metadata || new Map());
385385
}
386386
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import '../../jest-extensions.js';
19+
20+
import {
21+
makeData, makeVector,
22+
Schema, Field, RecordBatch,
23+
Struct, Int32
24+
} from 'apache-arrow';
25+
26+
describe('Struct with zero children', () => {
27+
28+
test('makeData with empty children preserves explicit length', () => {
29+
const data = makeData({ type: new Struct([]), length: 50, nullCount: 0, children: [] });
30+
expect(data).toHaveLength(50);
31+
});
32+
33+
test('makeData with empty children and no length defaults to 0', () => {
34+
const data = makeData({ type: new Struct([]), children: [] });
35+
expect(data).toHaveLength(0);
36+
});
37+
38+
test('setChildAt preserves numRows after column replacement', () => {
39+
const field = Field.new({ name: 'a', type: new Int32, nullable: true });
40+
const schema = new Schema([field]);
41+
const childData = makeData({ type: new Int32, length: 10, nullCount: 0 });
42+
const structData = makeData({
43+
type: new Struct(schema.fields),
44+
length: 10,
45+
nullCount: 0,
46+
children: [childData]
47+
});
48+
const batch = new RecordBatch(schema, structData);
49+
expect(batch.numRows).toBe(10);
50+
51+
const newChild = makeVector(new Int32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]));
52+
const newBatch = batch.setChildAt(0, newChild);
53+
expect(newBatch.numRows).toBe(10);
54+
});
55+
});

0 commit comments

Comments
 (0)