Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,720 changes: 894 additions & 826 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@uwdata/flechette",
"version": "2.5.0",
"version": "2.6.0",
"description": "Fast, lightweight access to Apache Arrow data.",
"keywords": [
"arrow",
Expand Down Expand Up @@ -36,15 +36,15 @@
"devDependencies": {
"@eslint/js": "^10.0.1",
"@rollup/plugin-terser": "^1.0.0",
"apache-arrow": "^21.1.0",
"eslint": "^10.3.0",
"globals": "^17.6.0",
"apache-arrow": "^21.2.0",
"eslint": "^10.12.0",
"globals": "^17.13.0",
"lz4js": "0.2.0",
"rimraf": "^6.1.3",
"rollup": "^4.60.3",
"rollup": "^4.64.1",
"rollup-plugin-bundle-size": "^1.0.3",
"typescript": "^6.0.3",
"vitest": "^4.1.5",
"typescript": "^7.0.2",
"vitest": "^5.0.3",
"zstd-codec": "0.1.5"
}
}
11 changes: 6 additions & 5 deletions src/build/builder.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/**
* @import { DataType, ExtractionOptions } from '../types.js'
* @import { BuilderContext, DictionaryContext } from './types.js'
* @import { BatchBuilder } from './builders/batch.js'
*/
import { batchType } from '../batch-type.js';
import { IntervalUnit, Type } from '../constants.js';
import { invalidDataType } from '../data-types.js';
import { isInt64ArrayType } from '../util/arrays.js';
import { toBigInt, toDateDay, toDecimal32, toFloat16, toTimestamp } from '../util/numbers.js';
import { toDateDay, toDateMillisecond, toDecimal32, toFloat16, toTimestamp } from '../util/numbers.js';
import { BinaryBuilder } from './builders/binary.js';
import { BoolBuilder } from './builders/bool.js';
import { DecimalBuilder } from './builders/decimal.js';
Expand All @@ -25,8 +26,8 @@ import { DirectBuilder, Int64Builder, TransformBuilder } from './builders/values
/**
* Create a context object for shared builder state.
* @param {ExtractionOptions} [options] Batch extraction options.
* @param {ReturnType<dictionaryContext>} [dictionaries]
* Context object for tracking dictionaries.
* @param {DictionaryContext} [dictionaries] Context object for tracking dictionaries.
* @returns {BuilderContext}
*/
export function builderContext(
options = {},
Expand All @@ -43,7 +44,7 @@ export function builderContext(
/**
* Returns a batch builder for the given type and builder context.
* @param {DataType} type A data type.
* @param {ReturnType<builderContext>} [ctx] A builder context.
* @param {BuilderContext} [ctx] A builder context.
* @returns {BatchBuilder}
*/
export function builder(type, ctx = builderContext()) {
Expand Down Expand Up @@ -72,7 +73,7 @@ export function builder(type, ctx = builderContext()) {
? new TransformBuilder(type, ctx, toDecimal32(type.scale))
: new DecimalBuilder(type, ctx);
case Type.Date:
return new TransformBuilder(type, ctx, type.unit ? toBigInt : toDateDay);
return new TransformBuilder(type, ctx, type.unit ? toDateMillisecond : toDateDay);
case Type.Timestamp:
return new TransformBuilder(type, ctx, toTimestamp(type.unit));
case Type.Interval:
Expand Down
19 changes: 9 additions & 10 deletions src/build/builders/dictionary.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @import { builderContext } from '../builder.js'
* @import { DictionaryType, ExtractionOptions } from '../../types.js'
* @import { BuilderContext, DictionaryContext, DictionaryValues } from '../types.js'
*/
import { Column } from '../../column.js';
import { keyString } from '../../util/strings.js';
Expand All @@ -10,17 +10,17 @@ import { ValidityBuilder } from './validity.js';

/**
* Create a context object for managing dictionary builders.
* @returns {DictionaryContext}
*/
export function dictionaryContext() {
const idMap = new Map;
const dicts = new Set;
return {
/**
* Get a dictionary values builder for the given dictionary type.
* @param {DictionaryType} type
* The dictionary type.
* @param {*} ctx The builder context.
* @returns {ReturnType<dictionaryValues>}
* @param {DictionaryType} type The dictionary type.
* @param {BuilderContext} ctx The builder context.
* @returns {DictionaryValues}
*/
get(type, ctx) {
// if a dictionary has a non-negative id, assume it was set
Expand Down Expand Up @@ -49,13 +49,12 @@ export function dictionaryContext() {

/**
* Builder helper for creating dictionary values.
* @param {DictionaryType} type
* The dictionary data type.
* @param {ReturnType<builderContext>} ctx
* The builder context.
* @param {DictionaryType} type The dictionary data type.
* @param {BuilderContext} ctx The builder context.
* @returns {DictionaryValues}
*/
export function dictionaryValues(type, ctx) {
const keys = Object.create(null);
const keys = /** @type {Record<string, number>} */ (Object.create(null));
const values = ctx.builder(type.dictionary);
const batches = [];

Expand Down
2 changes: 1 addition & 1 deletion src/build/column-from-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { columnFromValues } from './column-from-values.js';
* If not specified, type inference is attempted.
* @param {ColumnBuilderOptions} [options]
* Builder options for the generated column.
* @param {ReturnType<dictionaryContext>} [dicts]
* @param {ReturnType<typeof dictionaryContext>} [dicts]
* Builder context object, for internal use only.
* @returns {Column<T>} The generated column.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/build/column-from-values.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { isIterable } from '../util/objects.js';
* @param {DataType} [type] The data type.
* @param {ColumnBuilderOptions} [options]
* Builder options for the generated column.
* @param {ReturnType<dictionaryContext>} [dicts]
* @param {ReturnType<typeof dictionaryContext>} [dicts]
* Dictionary context object, for internal use only.
* @returns {Column<T>} The generated column.
*/
Expand Down
23 changes: 23 additions & 0 deletions src/build/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Batch } from "../batch.js";
import type { DataType, DictionaryType, ExtractionOptions } from "../types.ts";
import type { BatchBuilder } from "./builders/batch.js";

export interface DictionaryContext {
get(type: DictionaryType, ctx: BuilderContext): DictionaryValues;
finish(options: ExtractionOptions): void;
}

export interface DictionaryValues {
type: DictionaryType;
values: BatchBuilder;
add<T extends Batch<unknown>>(batch: T): T;
key(value: unknown): number;
finish(options: ExtractionOptions): void;
}

export interface BuilderContext {
batchType: (type: DataType) => BatchBuilder;
builder(type: DataType): BatchBuilder;
dictionary(type: DictionaryType): DictionaryValues;
finish: () => void;
}
2 changes: 1 addition & 1 deletion src/encode/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class Builder {
* Add a flatbuffer object (vtable).
* @param {number} numFields The maximum number of fields
* this object may include.
* @param {(tableBuilder: ReturnType<objectBuilder>) => void} [addFields]
* @param {(tableBuilder: ReturnType<typeof objectBuilder>) => void} [addFields]
* A callback function that writes all fields using an object builder.
* @returns {number} The object offset.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/encode/table-to-ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ function assembleRecordBatch(columns, batchIndex = 0, codec) {
* Visit a column batch, assembling buffer data.
* @param {DataType} type The data type.
* @param {Batch} batch The column batch.
* @param {ReturnType<assembleContext>} ctx The assembly context.
* @param {ReturnType<typeof assembleContext>} ctx The assembly context.
*/
function visit(type, batch, ctx) {
const { typeId } = type;
Expand Down
11 changes: 10 additions & 1 deletion src/util/numbers.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ export function toOffset(type) {
* @returns {number} The number of days.
*/
export function toDateDay(value) {
return (value / 864e5) | 0;
return Math.floor(value / 864e5);
}

/**
* Returns a day-divisible value from a millisecond timestamp.
* @param {number} value The millisecond timestamp.
* @returns {bigint} A UTC date-aligned millisecond timestamp.
*/
export function toDateMillisecond(value) {
return toBigInt(864e5 * toDateDay(value));
}

/**
Expand Down
27 changes: 18 additions & 9 deletions test/column-from-array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import { describe, it, expect } from "vitest";
import { IntervalUnit, TimeUnit, UnionMode, binary, bool, columnFromArray, dateDay, dateMillisecond, decimal, dictionary, duration, field, fixedSizeBinary, fixedSizeList, float16, float32, float64, int16, int32, int64, int8, interval, largeBinary, largeList, largeUtf8, list, map, nullType, runEndEncoded, struct, time, timeMicrosecond, timeMillisecond, timeNanosecond, timeSecond, timestamp, uint16, uint32, uint64, uint8, union, utf8 } from '../src/index.js';
import { isTypedArray } from '../src/util/arrays.js';

function test(values, type, options) {
const col = columnFromArray(values, type, options);
function test(values, type, options = {}) {
const { expected = values, ...opt } = options;
const col = columnFromArray(values, type, opt);
if (type) expect(col.type).toBe(type);
if (!type && isTypedArray(values)) {
// check that inferred data type maintains input array type
expect(col.data[0].values.constructor).toBe(values.constructor);
}
expect(col.length).toBe(values.length);
expect(Array.from(col)).toStrictEqual(Array.from(values));
expect(col.length).toBe(expected.length);
expect(Array.from(col)).toStrictEqual(Array.from(expected));
return col;
}

Expand Down Expand Up @@ -127,13 +128,20 @@ describe('columnFromArray', () => {
it('builds date columns', () => {
const dates = [
new Date(Date.UTC(2000, 0, 1)),
new Date(Date.UTC(1700, 6, 30, 12)),
new Date(Date.UTC(1973, 3, 20, 12)),
new Date(Date.UTC(1989, 4, 5))
];
const expected = [
new Date(Date.UTC(2000, 0, 1)),
new Date(Date.UTC(1700, 6, 30)),
new Date(Date.UTC(1973, 3, 20)),
new Date(Date.UTC(1989, 4, 5))
];
test(dates.map(v => +v), dateDay());
test(dates.map(v => +v), dateMillisecond());
test(dates, dateDay(), { useDate: true });
test(dates, dateMillisecond(), { useDate: true });
test(dates.map(Number), dateDay(), { expected: expected.map(Number) });
test(dates, dateDay(), { useDate: true, expected });
test(dates.map(Number), dateMillisecond(), { expected: expected.map(Number) });
test(dates, dateMillisecond(), { useDate: true, expected });
});

it('builds time columns', () => {
Expand Down Expand Up @@ -163,7 +171,8 @@ describe('columnFromArray', () => {
it('builds timestamp columns', () => {
const dates = [
new Date(Date.UTC(2000, 0, 1)),
new Date(Date.UTC(1973, 3, 20)),
new Date(Date.UTC(1700, 6, 30, 12)),
new Date(Date.UTC(1973, 3, 20, 12)),
new Date(Date.UTC(1989, 4, 5))
];

Expand Down
Loading