This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-js.git


The following commit(s) were added to refs/heads/main by this push:
     new 19d9de3  fix: Pass explicit length in Struct makeData calls (#404)
19d9de3 is described below

commit 19d9de3d925e76a4df7a02f5c92d2f15ee240db0
Author: Rusty Conover <[email protected]>
AuthorDate: Thu Mar 12 02:54:17 2026 -0400

    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 <[email protected]>
---
 src/recordbatch.ts                           |  4 +-
 test/unit/data/struct-zero-children-tests.ts | 55 ++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/recordbatch.ts b/src/recordbatch.ts
index 7c876dc..f70c69f 100644
--- a/src/recordbatch.ts
+++ b/src/recordbatch.ts
@@ -261,7 +261,7 @@ export class RecordBatch<T extends TypeMap = any> {
             const field = fields[index].clone({ type: child.type });
             [fields[index], children[index]] = [field, child.data[0]];
             schema = new Schema(fields, new Map(this.schema.metadata));
-            data = makeData({ type: new Struct<T>(fields), children });
+            data = makeData({ type: new Struct<T>(fields), length: 
data.length, children });
         }
         return new RecordBatch(schema, data, this._metadata);
     }
@@ -380,7 +380,7 @@ function collectDictionaries(fields: Field[], children: 
readonly Data[], diction
 export class _InternalEmptyPlaceholderRecordBatch<T extends TypeMap = any> 
extends RecordBatch<T> {
     constructor(schema: Schema<T>, metadata?: Map<string, string>) {
         const children = schema.fields.map((f) => makeData({ type: f.type }));
-        const data = makeData({ type: new Struct<T>(schema.fields), nullCount: 
0, children });
+        const data = makeData({ type: new Struct<T>(schema.fields), length: 0, 
nullCount: 0, children });
         super(schema, data, metadata || new Map());
     }
 }
diff --git a/test/unit/data/struct-zero-children-tests.ts 
b/test/unit/data/struct-zero-children-tests.ts
new file mode 100644
index 0000000..353034a
--- /dev/null
+++ b/test/unit/data/struct-zero-children-tests.ts
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import '../../jest-extensions.js';
+
+import {
+    makeData, makeVector,
+    Schema, Field, RecordBatch,
+    Struct, Int32
+} from 'apache-arrow';
+
+describe('Struct with zero children', () => {
+
+    test('makeData with empty children preserves explicit length', () => {
+        const data = makeData({ type: new Struct([]), length: 50, nullCount: 
0, children: [] });
+        expect(data).toHaveLength(50);
+    });
+
+    test('makeData with empty children and no length defaults to 0', () => {
+        const data = makeData({ type: new Struct([]), children: [] });
+        expect(data).toHaveLength(0);
+    });
+
+    test('setChildAt preserves numRows after column replacement', () => {
+        const field = Field.new({ name: 'a', type: new Int32, nullable: true 
});
+        const schema = new Schema([field]);
+        const childData = makeData({ type: new Int32, length: 10, nullCount: 0 
});
+        const structData = makeData({
+            type: new Struct(schema.fields),
+            length: 10,
+            nullCount: 0,
+            children: [childData]
+        });
+        const batch = new RecordBatch(schema, structData);
+        expect(batch.numRows).toBe(10);
+
+        const newChild = makeVector(new Int32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 
10]));
+        const newBatch = batch.setChildAt(0, newChild);
+        expect(newBatch.numRows).toBe(10);
+    });
+});

Reply via email to