diff --git a/src/builder/struct.ts b/src/builder/struct.ts index e1beb3d3..64e60637 100644 --- a/src/builder/struct.ts +++ b/src/builder/struct.ts @@ -21,9 +21,23 @@ import { Field } from '../schema.js'; import { Builder } from '../builder.js'; import { Struct, TypeMap } from '../type.js'; +/** @ignore */ +type StructValue = Struct['TValue'] | { [P in keyof T]: T[P]['TValue'] }; + /** @ignore */ export class StructBuilder extends Builder, TNull> { - public setValue(index: number, value: Struct['TValue']) { + public append(value: StructValue | TNull) { + return this.set(this.length, value as any); + } + + public set(index: number, value: StructValue | TNull) { + if (this.setValid(index, this.isValid(value as any))) { + this.setValue(index, value as StructValue); + } + return this; + } + + public setValue(index: number, value: StructValue) { const { children, type } = this; switch (Array.isArray(value) || value.constructor) { case true: return type.children.forEach((_, i) => children[i].set(index, value[i])); diff --git a/test/tsconfig.json b/test/tsconfig.json index e1ad1388..e612ec4e 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -4,6 +4,7 @@ "compilerOptions": { "target": "ESNext", "module": "NodeNext", + "moduleResolution": "NodeNext", "rootDir": "../", "allowJs": true, "declaration": false, diff --git a/test/unit/builders/struct-builder-plain-object-tests.ts b/test/unit/builders/struct-builder-plain-object-tests.ts new file mode 100644 index 00000000..56774fd4 --- /dev/null +++ b/test/unit/builders/struct-builder-plain-object-tests.ts @@ -0,0 +1,46 @@ +// 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 { makeBuilder, Field, Struct, StructBuilder, TimestampMillisecond, Float64 } from '../../../src/Arrow.js'; + +interface ValueType { + time: TimestampMillisecond; + value: Float64; +} + +type Value = { + time: number; + value: number; +}; + +test('StructBuilder accepts plain object and produces correct values', () => { + const children = [ + new Field('time', new TimestampMillisecond()), + new Field('value', new Float64()), + ]; + const structType = new Struct(children as any); + const builder = makeBuilder({ type: structType, nullValues: [null, undefined] }) as StructBuilder; + + const value: Value = { time: 1_630_000_000_000, value: 42.5 }; + builder.append(value); + const vec = builder.finish().toVector(); + const row = vec.get(0)! as any; + + expect(row.time).toBe(value.time); + expect(row.value).toBeCloseTo(value.value); + expect(row.toJSON()).toEqual({ time: value.time, value: value.value }); +});