Skip to content

Commit ea1c8db

Browse files
committed
fix writing empty tables
1 parent 1d0b369 commit ea1c8db

4 files changed

Lines changed: 42 additions & 13 deletions

File tree

js/src/ipc/writer.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { JSONTypeAssembler } from '../visitor/jsontypeassembler';
3333
import { JSONVectorAssembler } from '../visitor/jsonvectorassembler';
3434
import { ArrayBufferViewInput, toUint8Array } from '../util/buffer';
3535
import { Writable, ReadableInterop, ReadableDOMStreamOptions } from '../io/interfaces';
36-
import { isPromise, isAsyncIterable, isWritableDOMStream, isWritableNodeStream } from '../util/compat';
36+
import { isPromise, isAsyncIterable, isWritableDOMStream, isWritableNodeStream, isIterable } from '../util/compat';
3737

3838
export class RecordBatchWriter<T extends { [key: string]: DataType } = any> extends ReadableInterop<Uint8Array> implements Writable<RecordBatch<T>> {
3939

@@ -140,21 +140,36 @@ export class RecordBatchWriter<T extends { [key: string]: DataType } = any> exte
140140
return this;
141141
}
142142

143-
public write(chunk?: Table<T> | RecordBatch<T> | null) {
144-
let schema: Schema<T> | null;
143+
public write(payload?: Table<T> | RecordBatch<T> | Iterable<RecordBatch<T>> | null) {
144+
145+
let schema: Schema<T> | null = null;
146+
145147
if (!this._sink) {
146148
throw new Error(`RecordBatchWriter is closed`);
147-
} else if (!chunk || !(schema = chunk.schema)) {
149+
} else if (payload === null || payload === undefined) {
150+
return this.finish() && undefined;
151+
} else if (payload instanceof Table && !(schema = payload.schema)) {
148152
return this.finish() && undefined;
149-
} else if (schema !== this._schema) {
153+
} else if (payload instanceof RecordBatch && !(schema = payload.schema)) {
154+
return this.finish() && undefined;
155+
}
156+
157+
if (schema && !schema.compareTo(this._schema)) {
150158
if (this._started && this._autoDestroy) {
151159
return this.close();
152160
}
153161
this.reset(this._sink, schema);
154162
}
155-
(chunk instanceof Table)
156-
? this.writeAll(chunk.chunks)
157-
: this._writeRecordBatch(chunk);
163+
164+
if (payload instanceof RecordBatch) {
165+
if (payload.length > 0) {
166+
this._writeRecordBatch(payload);
167+
}
168+
} else if (payload instanceof Table) {
169+
this.writeAll(payload.chunks);
170+
} else if (isIterable(payload)) {
171+
this.writeAll(payload);
172+
}
158173
}
159174

160175
protected _writeMessage<T extends MessageHeader>(message: Message<T>, alignment = 8) {
@@ -363,7 +378,11 @@ export class RecordBatchJSONWriter<T extends { [key: string]: DataType } = any>
363378

364379
/** @ignore */
365380
function writeAll<T extends { [key: string]: DataType } = any>(writer: RecordBatchWriter<T>, input: Table<T> | Iterable<RecordBatch<T>>) {
366-
const chunks = (input instanceof Table) ? input.chunks : input;
381+
let chunks = input as Iterable<RecordBatch<T>>;
382+
if (input instanceof Table) {
383+
chunks = input.chunks;
384+
writer.reset(undefined, input.schema);
385+
}
367386
for (const batch of chunks) {
368387
writer.write(batch);
369388
}

js/src/table.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,7 @@ export class Table<T extends { [key: string]: DataType } = any>
179179
throw new TypeError('Table must be initialized with a Schema or at least one RecordBatch');
180180
}
181181

182-
if (!chunks[0]) { chunks[0] = new RecordBatch(schema, 0, []); }
183-
184-
super(chunks[0].type, chunks);
182+
super(new Struct<T>(schema.fields), chunks);
185183

186184
this._schema = schema;
187185
this._chunks = chunks;

js/src/visitor/vectorassembler.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ export class VectorAssembler extends Visitor {
5959

6060
/** @nocollapse */
6161
public static assemble<T extends Vector | RecordBatch>(...args: (T | T[])[]) {
62-
return new VectorAssembler().visitMany(selectVectorChildrenArgs(RecordBatch, args))[0];
62+
const assembler = new VectorAssembler();
63+
const vectorChildren = selectVectorChildrenArgs(RecordBatch, args);
64+
const [assembleResult = assembler] = assembler.visitMany(vectorChildren);
65+
return assembleResult;
6366
}
6467

6568
private constructor() { super(); }

js/test/unit/table/serialize-tests.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ function createTable<T extends { [key: string]: DataType } = any>(schema: Schema
3030
}
3131

3232
describe('Table#serialize()', () => {
33+
34+
test(`Table#empty round-trips through serialization`, () => {
35+
const source = Table.empty();
36+
expect(source.length).toBe(0);
37+
expect(source.numCols).toBe(0);
38+
const result = Table.from(source.serialize());
39+
expect(result).toEqualTable(source);
40+
});
41+
3342
const chunkLengths = [] as number[];
3443
for (let i = -1; ++i < 3;) {
3544
chunkLengths[i] = (Math.random() * 100) | 0;

0 commit comments

Comments
 (0)