@thi.ng/column-store 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/api.d.ts +31 -2
- package/bitmap.d.ts +1 -0
- package/bitmap.js +18 -4
- package/columns/acolumn.d.ts +1 -0
- package/columns/acolumn.js +7 -11
- package/columns/dict-tuple.d.ts +1 -0
- package/columns/dict-tuple.js +10 -1
- package/columns/dict.d.ts +1 -0
- package/columns/dict.js +11 -1
- package/columns/plain.d.ts +1 -0
- package/columns/plain.js +11 -1
- package/columns/tuple.d.ts +1 -0
- package/columns/tuple.js +10 -1
- package/columns/typedarray.d.ts +1 -0
- package/columns/typedarray.js +11 -1
- package/columns/vector.d.ts +2 -1
- package/columns/vector.js +20 -3
- package/internal/indexof.d.ts +6 -0
- package/internal/indexof.js +40 -5
- package/internal/serialize.d.ts +1 -1
- package/package.json +2 -2
- package/query.js +12 -19
- package/table.d.ts +1 -0
- package/table.js +3 -0
package/README.md
CHANGED
package/api.d.ts
CHANGED
|
@@ -92,15 +92,44 @@ export interface IColumn {
|
|
|
92
92
|
validate(value: any): boolean;
|
|
93
93
|
/**
|
|
94
94
|
* Searches for `value` in the column data, optionally constrained to given
|
|
95
|
-
* `start`/`end` range
|
|
96
|
-
* otherwise -1.
|
|
95
|
+
* `start`/`end` range (end index is exclusive and defaults to current table
|
|
96
|
+
* length). If found, returns row ID of first occurrence, otherwise -1.
|
|
97
97
|
*
|
|
98
98
|
* @param value
|
|
99
99
|
* @param start
|
|
100
100
|
* @param end
|
|
101
101
|
*/
|
|
102
102
|
indexOf(value: any, start?: number, end?: number): number;
|
|
103
|
+
/**
|
|
104
|
+
* Searches for `value` in the column data in reverse order (from the last
|
|
105
|
+
* row), optionally constrained to given `start`/`end` range (end index is
|
|
106
|
+
* exclusive and defaults to current table length). If found, returns row ID
|
|
107
|
+
* of first occurrence, otherwise -1.
|
|
108
|
+
*
|
|
109
|
+
* @param value
|
|
110
|
+
* @param start
|
|
111
|
+
* @param end
|
|
112
|
+
*/
|
|
113
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
114
|
+
/**
|
|
115
|
+
* Similar to {@link IColumn.indexOf}, but applies given predicate function
|
|
116
|
+
* to each row value. Returns index of first row for which the predicate is
|
|
117
|
+
* truthy, otherwise returns -1.
|
|
118
|
+
*
|
|
119
|
+
* @param pred
|
|
120
|
+
* @param start
|
|
121
|
+
* @param end
|
|
122
|
+
*/
|
|
103
123
|
findIndex(pred: Predicate<any>, start?: number, end?: number): number;
|
|
124
|
+
/**
|
|
125
|
+
* Similar to {@link IColumn.lastIndexOf}, but applies given predicate
|
|
126
|
+
* function to each row value. Returns index of first row for which the
|
|
127
|
+
* predicate is truthy, otherwise returns -1.
|
|
128
|
+
*
|
|
129
|
+
* @param pred
|
|
130
|
+
* @param start
|
|
131
|
+
* @param end
|
|
132
|
+
*/
|
|
104
133
|
findLastIndex(pred: Predicate<any>, start?: number, end?: number): number;
|
|
105
134
|
/**
|
|
106
135
|
* Returns value at given row.
|
package/bitmap.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export declare class Bitfield {
|
|
|
28
28
|
constructor(buffer?: Uint32Array | undefined);
|
|
29
29
|
ones(max?: number): Generator<number, void, unknown>;
|
|
30
30
|
first(start?: number, end?: number): number;
|
|
31
|
+
last(start?: number, end?: number): number;
|
|
31
32
|
setBit(id: number): void;
|
|
32
33
|
clearBit(id: number): void;
|
|
33
34
|
fill(x: 0 | 1, start: number, end: number): this;
|
package/bitmap.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __clampRange } from "./internal/indexof.js";
|
|
2
2
|
class BitmapIndex {
|
|
3
3
|
index = /* @__PURE__ */ new Map();
|
|
4
4
|
/**
|
|
@@ -66,9 +66,7 @@ class Bitfield {
|
|
|
66
66
|
first(start = 0, end) {
|
|
67
67
|
const { buffer } = this;
|
|
68
68
|
if (!buffer) return -1;
|
|
69
|
-
|
|
70
|
-
start = __clamp(start, 0, max);
|
|
71
|
-
end = __clamp(end ?? max, 0, max);
|
|
69
|
+
[start, end] = __clampRange(buffer.length << 5, start, end);
|
|
72
70
|
if (start >= end) return -1;
|
|
73
71
|
for (let i = start >>> 5, n = Math.min(Math.ceil(end / 32), buffer.length); i < n; i++) {
|
|
74
72
|
let bits = buffer[i];
|
|
@@ -81,6 +79,22 @@ class Bitfield {
|
|
|
81
79
|
}
|
|
82
80
|
return -1;
|
|
83
81
|
}
|
|
82
|
+
last(start = 0, end) {
|
|
83
|
+
const { buffer } = this;
|
|
84
|
+
if (!buffer) return -1;
|
|
85
|
+
[start, end] = __clampRange(buffer.length << 5, start, end);
|
|
86
|
+
if (start >= end) return -1;
|
|
87
|
+
for (let i = end >>> 5, n = start >>> 5; i >= n; i--) {
|
|
88
|
+
let bits = buffer[i];
|
|
89
|
+
while (bits) {
|
|
90
|
+
const msb = Math.clz32(bits) ^ 31;
|
|
91
|
+
const x = (i << 5) + msb;
|
|
92
|
+
if (x >= start && x < end) return x;
|
|
93
|
+
bits ^= 1 << msb;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return -1;
|
|
97
|
+
}
|
|
84
98
|
setBit(id) {
|
|
85
99
|
const w = id >>> 5;
|
|
86
100
|
this.ensure(w)[w] |= 1 << (id & 31);
|
package/columns/acolumn.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare abstract class AColumn<T extends Row = Row> implements IColumn {
|
|
|
21
21
|
abstract getRow(i: number): any;
|
|
22
22
|
abstract getRowKey(i: number): any;
|
|
23
23
|
abstract indexOf(value: any, start?: number, end?: number): number;
|
|
24
|
+
abstract lastIndexOf(value: any, start?: number, end?: number): number;
|
|
24
25
|
findIndex(pred: Predicate<any>, start?: number, end?: number): number;
|
|
25
26
|
findLastIndex(pred: Predicate<any>, start?: number, end?: number): number;
|
|
26
27
|
encode(value: any): any;
|
package/columns/acolumn.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../api.js";
|
|
4
4
|
import { BitmapIndex } from "../bitmap.js";
|
|
5
5
|
import { __columnError } from "../internal/checks.js";
|
|
6
|
-
import {
|
|
6
|
+
import { __clampRange } from "../internal/indexof.js";
|
|
7
7
|
class AColumn {
|
|
8
8
|
constructor(id, table) {
|
|
9
9
|
this.id = id;
|
|
@@ -18,19 +18,15 @@ class AColumn {
|
|
|
18
18
|
this.updateBitmap();
|
|
19
19
|
}
|
|
20
20
|
findIndex(pred, start = 0, end) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end = __clamp(end ?? max, 0, max);
|
|
24
|
-
for (let i = start; i <= end; i++) {
|
|
21
|
+
[start, end] = __clampRange(this.table.length, start, end);
|
|
22
|
+
for (let i = start; i < end; i++) {
|
|
25
23
|
if (pred(this.getRow(i))) return i;
|
|
26
24
|
}
|
|
27
25
|
return -1;
|
|
28
26
|
}
|
|
29
27
|
findLastIndex(pred, start = 0, end) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end = __clamp(end ?? max, 0, max);
|
|
33
|
-
for (let i = end; i >= start; i--) {
|
|
28
|
+
[start, end] = __clampRange(this.table.length, start, end);
|
|
29
|
+
for (let i = end; i-- > start; ) {
|
|
34
30
|
if (pred(this.getRow(i))) return i;
|
|
35
31
|
}
|
|
36
32
|
return -1;
|
|
@@ -60,11 +56,11 @@ class AColumn {
|
|
|
60
56
|
if (!bitmap) return;
|
|
61
57
|
bitmap.clear();
|
|
62
58
|
for (let i = 0, n = this.table.length; i < n; i++) {
|
|
63
|
-
const value = this.
|
|
59
|
+
const value = this.getRowKey(i);
|
|
64
60
|
if (value == null) continue;
|
|
65
61
|
if (isArray) {
|
|
66
62
|
for (let x of value) bitmap.setBit(x, i);
|
|
67
|
-
} else bitmap.setBit(
|
|
63
|
+
} else bitmap.setBit(value, i);
|
|
68
64
|
}
|
|
69
65
|
}
|
|
70
66
|
ensureValue(val) {
|
package/columns/dict-tuple.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class DictTupleColumn<T extends Row = Row> extends AColumn<T> {
|
|
|
16
16
|
valueKey(value: any): (number | null)[];
|
|
17
17
|
removeRow(i: number): void;
|
|
18
18
|
indexOf(value: any, start?: number, end?: number): number;
|
|
19
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
19
20
|
replaceValue(currValue: any, newValue: any): boolean;
|
|
20
21
|
toJSON(): {
|
|
21
22
|
dict: {
|
package/columns/dict-tuple.js
CHANGED
|
@@ -2,7 +2,7 @@ import { BidirIndex } from "@thi.ng/bidir-index";
|
|
|
2
2
|
import { isArray } from "@thi.ng/checks/is-array";
|
|
3
3
|
import { FLAG_UNIQUE } from "../api.js";
|
|
4
4
|
import { __validateArrayValue } from "../internal/checks.js";
|
|
5
|
-
import { __indexOfTuple } from "../internal/indexof.js";
|
|
5
|
+
import { __indexOfTuple, __lastIndexOfTuple } from "../internal/indexof.js";
|
|
6
6
|
import { __serializeDict } from "../internal/serialize.js";
|
|
7
7
|
import { AColumn } from "./acolumn.js";
|
|
8
8
|
class DictTupleColumn extends AColumn {
|
|
@@ -65,6 +65,15 @@ class DictTupleColumn extends AColumn {
|
|
|
65
65
|
end
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
|
+
lastIndexOf(value, start = 0, end) {
|
|
69
|
+
return __lastIndexOfTuple(
|
|
70
|
+
value != null ? this.encode(value) : null,
|
|
71
|
+
this.values,
|
|
72
|
+
this.table.length,
|
|
73
|
+
start,
|
|
74
|
+
end
|
|
75
|
+
);
|
|
76
|
+
}
|
|
68
77
|
replaceValue(currValue, newValue) {
|
|
69
78
|
const { dict, values, bitmap } = this;
|
|
70
79
|
const res = dict.renameKey(currValue, newValue);
|
package/columns/dict.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class DictColumn<T extends Row = Row> extends AColumn<T> {
|
|
|
16
16
|
valueKey(value: any): number | number[] | undefined;
|
|
17
17
|
removeRow(i: number): void;
|
|
18
18
|
indexOf(value: any, start?: number, end?: number): number;
|
|
19
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
19
20
|
replaceValue(currValue: any, newValue: any): boolean;
|
|
20
21
|
toJSON(): {
|
|
21
22
|
dict: {
|
package/columns/dict.js
CHANGED
|
@@ -4,7 +4,7 @@ import { decodeBinary, encodeBinary } from "@thi.ng/rle-pack/binary";
|
|
|
4
4
|
import { decodeSimple, encodeSimple } from "@thi.ng/rle-pack/simple";
|
|
5
5
|
import { FLAG_RLE } from "../api.js";
|
|
6
6
|
import { __validateValue } from "../internal/checks.js";
|
|
7
|
-
import { __indexOfSingle } from "../internal/indexof.js";
|
|
7
|
+
import { __indexOfSingle, __lastIndexOfSingle } from "../internal/indexof.js";
|
|
8
8
|
import { __serializeDict } from "../internal/serialize.js";
|
|
9
9
|
import { AColumn } from "./acolumn.js";
|
|
10
10
|
class DictColumn extends AColumn {
|
|
@@ -68,6 +68,16 @@ class DictColumn extends AColumn {
|
|
|
68
68
|
end
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
|
+
lastIndexOf(value, start = 0, end) {
|
|
72
|
+
return __lastIndexOfSingle(
|
|
73
|
+
this.encode(value),
|
|
74
|
+
this.values,
|
|
75
|
+
this.bitmap,
|
|
76
|
+
this.table.length,
|
|
77
|
+
start,
|
|
78
|
+
end
|
|
79
|
+
);
|
|
80
|
+
}
|
|
71
81
|
replaceValue(currValue, newValue) {
|
|
72
82
|
const { dict, values, bitmap } = this;
|
|
73
83
|
const res = dict.renameKey(currValue, newValue);
|
package/columns/plain.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare class PlainColumn<T extends Row = Row> extends AColumn<T> {
|
|
|
11
11
|
valueKey(x: any): any;
|
|
12
12
|
removeRow(i: number): void;
|
|
13
13
|
indexOf(value: any, start?: number, end?: number): number;
|
|
14
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
14
15
|
replaceValue(currValue: any, newValue: any): boolean;
|
|
15
16
|
toJSON(): {
|
|
16
17
|
values: any[];
|
package/columns/plain.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { decodeSimple, encodeSimple } from "@thi.ng/rle-pack/simple";
|
|
2
2
|
import { FLAG_RLE } from "../api.js";
|
|
3
3
|
import { __validateValue } from "../internal/checks.js";
|
|
4
|
-
import { __indexOfSingle } from "../internal/indexof.js";
|
|
4
|
+
import { __indexOfSingle, __lastIndexOfSingle } from "../internal/indexof.js";
|
|
5
5
|
import { __replaceValue } from "../internal/replace.js";
|
|
6
6
|
import { AColumn } from "./acolumn.js";
|
|
7
7
|
class PlainColumn extends AColumn {
|
|
@@ -46,6 +46,16 @@ class PlainColumn extends AColumn {
|
|
|
46
46
|
end
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
|
+
lastIndexOf(value, start = 0, end) {
|
|
50
|
+
return __lastIndexOfSingle(
|
|
51
|
+
value,
|
|
52
|
+
this.values,
|
|
53
|
+
this.bitmap,
|
|
54
|
+
this.table.length,
|
|
55
|
+
start,
|
|
56
|
+
end
|
|
57
|
+
);
|
|
58
|
+
}
|
|
49
59
|
replaceValue(currValue, newValue) {
|
|
50
60
|
return __replaceValue(this.bitmap, this.values, currValue, newValue);
|
|
51
61
|
}
|
package/columns/tuple.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare class TupleColumn<T extends Row = Row> extends AColumn<T> {
|
|
|
13
13
|
valueKey(value: any): any[];
|
|
14
14
|
removeRow(i: number): void;
|
|
15
15
|
indexOf(value: any, start?: number, end?: number): number;
|
|
16
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
16
17
|
replaceValue(currValue: any, newValue: any): boolean;
|
|
17
18
|
toJSON(): {
|
|
18
19
|
values: Nullable<number[]>[];
|
package/columns/tuple.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isArray } from "@thi.ng/checks/is-array";
|
|
2
2
|
import { FLAG_UNIQUE } from "../api.js";
|
|
3
3
|
import { __validateArrayValue } from "../internal/checks.js";
|
|
4
|
-
import { __indexOfTuple } from "../internal/indexof.js";
|
|
4
|
+
import { __indexOfTuple, __lastIndexOfTuple } from "../internal/indexof.js";
|
|
5
5
|
import { AColumn } from "./acolumn.js";
|
|
6
6
|
class TupleColumn extends AColumn {
|
|
7
7
|
values = [];
|
|
@@ -48,6 +48,15 @@ class TupleColumn extends AColumn {
|
|
|
48
48
|
end
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
|
+
lastIndexOf(value, start = 0, end) {
|
|
52
|
+
return __lastIndexOfTuple(
|
|
53
|
+
value,
|
|
54
|
+
this.values,
|
|
55
|
+
this.table.length,
|
|
56
|
+
start,
|
|
57
|
+
end
|
|
58
|
+
);
|
|
59
|
+
}
|
|
51
60
|
replaceValue(currValue, newValue) {
|
|
52
61
|
const { values, bitmap } = this;
|
|
53
62
|
const isUnique = this.spec.flags & FLAG_UNIQUE;
|
package/columns/typedarray.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare class TypedArrayColumn<T extends Row = Row> extends AColumn<T> {
|
|
|
17
17
|
valueKey(value: any): number | number[];
|
|
18
18
|
removeRow(i: number): void;
|
|
19
19
|
indexOf(value: any, start?: number, end?: number): number;
|
|
20
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
20
21
|
replaceValue(currValue: any, newValue: any): boolean;
|
|
21
22
|
toJSON(): {
|
|
22
23
|
values: any[];
|
package/columns/typedarray.js
CHANGED
|
@@ -4,7 +4,7 @@ import { isNumber } from "@thi.ng/checks/is-number";
|
|
|
4
4
|
import {
|
|
5
5
|
LIMITS
|
|
6
6
|
} from "../api.js";
|
|
7
|
-
import { __indexOfSingle } from "../internal/indexof.js";
|
|
7
|
+
import { __indexOfSingle, __lastIndexOfSingle } from "../internal/indexof.js";
|
|
8
8
|
import { __replaceValue } from "../internal/replace.js";
|
|
9
9
|
import { __deserializeTyped, __serializeTyped } from "../internal/serialize.js";
|
|
10
10
|
import { AColumn } from "./acolumn.js";
|
|
@@ -78,6 +78,16 @@ class TypedArrayColumn extends AColumn {
|
|
|
78
78
|
end
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
|
+
lastIndexOf(value, start = 0, end) {
|
|
82
|
+
return __lastIndexOfSingle(
|
|
83
|
+
value,
|
|
84
|
+
this.values,
|
|
85
|
+
this.bitmap,
|
|
86
|
+
this.table.length,
|
|
87
|
+
start,
|
|
88
|
+
end
|
|
89
|
+
);
|
|
90
|
+
}
|
|
81
91
|
replaceValue(currValue, newValue) {
|
|
82
92
|
return __replaceValue(this.bitmap, this.values, currValue, newValue);
|
|
83
93
|
}
|
package/columns/vector.d.ts
CHANGED
|
@@ -13,11 +13,12 @@ export declare class VectorColumn<T extends Row = Row> extends AColumn<T> {
|
|
|
13
13
|
load({ values }: SerializedColumn): void;
|
|
14
14
|
validate(value: any): boolean;
|
|
15
15
|
setRow(i: number, value: any): void;
|
|
16
|
-
getRow(i: number):
|
|
16
|
+
getRow(i: number): Float32Array<ArrayBufferLike> | Float64Array<ArrayBufferLike> | Int8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Uint8ClampedArray<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>;
|
|
17
17
|
getRowKey(i: number): string;
|
|
18
18
|
valueKey(value: any): string | string[];
|
|
19
19
|
removeRow(i: number): void;
|
|
20
20
|
indexOf(value: any, start?: number, end?: number): number;
|
|
21
|
+
lastIndexOf(value: any, start?: number, end?: number): number;
|
|
21
22
|
replaceValue(): boolean;
|
|
22
23
|
toJSON(): {
|
|
23
24
|
values: any[];
|
package/columns/vector.js
CHANGED
|
@@ -6,6 +6,7 @@ import { unsupportedOp } from "@thi.ng/errors/unsupported";
|
|
|
6
6
|
import {
|
|
7
7
|
LIMITS
|
|
8
8
|
} from "../api.js";
|
|
9
|
+
import { __clampRange } from "../internal/indexof.js";
|
|
9
10
|
import { __deserializeTyped, __serializeTyped } from "../internal/serialize.js";
|
|
10
11
|
import { AColumn } from "./acolumn.js";
|
|
11
12
|
class VectorColumn extends AColumn {
|
|
@@ -76,11 +77,10 @@ class VectorColumn extends AColumn {
|
|
|
76
77
|
this.values.fill(0, (length - 1) * size);
|
|
77
78
|
this.bitmap?.removeBit(i);
|
|
78
79
|
}
|
|
79
|
-
indexOf(value, start = 0, end
|
|
80
|
+
indexOf(value, start = 0, end) {
|
|
80
81
|
if (value == null) return -1;
|
|
81
82
|
const { values, bitmap, size } = this;
|
|
82
|
-
start =
|
|
83
|
-
end = Math.min(end, this.table.length);
|
|
83
|
+
[start, end] = __clampRange(this.table.length, start, end);
|
|
84
84
|
if (bitmap) {
|
|
85
85
|
return bitmap.index.get(this.valueKey(value))?.first(start, end) ?? -1;
|
|
86
86
|
}
|
|
@@ -94,6 +94,23 @@ class VectorColumn extends AColumn {
|
|
|
94
94
|
}
|
|
95
95
|
return -1;
|
|
96
96
|
}
|
|
97
|
+
lastIndexOf(value, start = 0, end) {
|
|
98
|
+
if (value == null || value.length !== this.size) return -1;
|
|
99
|
+
const { values, bitmap, size } = this;
|
|
100
|
+
[start, end] = __clampRange(this.table.length, start, end);
|
|
101
|
+
if (bitmap) {
|
|
102
|
+
return bitmap.index.get(this.valueKey(value))?.last(start, end) ?? -1;
|
|
103
|
+
}
|
|
104
|
+
start *= size;
|
|
105
|
+
let i, j;
|
|
106
|
+
outer: for (i = end * size; (i -= size) >= start; ) {
|
|
107
|
+
for (j = 0; j < size; j++) {
|
|
108
|
+
if (values[i + j] !== value[j]) continue outer;
|
|
109
|
+
}
|
|
110
|
+
return i / size;
|
|
111
|
+
}
|
|
112
|
+
return -1;
|
|
113
|
+
}
|
|
97
114
|
replaceValue() {
|
|
98
115
|
unsupportedOp("TODO");
|
|
99
116
|
}
|
package/internal/indexof.d.ts
CHANGED
|
@@ -3,7 +3,13 @@ import type { BitmapIndex } from "../bitmap.js";
|
|
|
3
3
|
/** @internal */
|
|
4
4
|
export declare const __indexOfSingle: (needle: any, values: ArrayLike<any>, bitmap: Maybe<BitmapIndex>, max: number, start: number, end?: number) => number;
|
|
5
5
|
/** @internal */
|
|
6
|
+
export declare const __lastIndexOfSingle: (needle: any, values: ArrayLike<any>, bitmap: Maybe<BitmapIndex>, max: number, start: number, end?: number) => number;
|
|
7
|
+
/** @internal */
|
|
6
8
|
export declare const __indexOfTuple: (needle: ArrayLike<any> | null, values: ArrayLike<any>, max: number, start: number, end?: number) => number;
|
|
7
9
|
/** @internal */
|
|
10
|
+
export declare const __lastIndexOfTuple: (needle: ArrayLike<any> | null, values: ArrayLike<any>, max: number, start: number, end?: number) => number;
|
|
11
|
+
/** @internal */
|
|
8
12
|
export declare const __clamp: (x: number, a: number, b: number) => number;
|
|
13
|
+
/** @internal */
|
|
14
|
+
export declare const __clampRange: (max: number, start: number, end?: number) => number[];
|
|
9
15
|
//# sourceMappingURL=indexof.d.ts.map
|
package/internal/indexof.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
const __indexOfSingle = (needle, values, bitmap, max, start, end = max) => {
|
|
2
|
-
start =
|
|
3
|
-
end = __clamp(end, 0, max);
|
|
2
|
+
[start, end] = __clampRange(max, start, end);
|
|
4
3
|
if (bitmap) return bitmap.index.get(needle)?.first(start, end) ?? -1;
|
|
5
4
|
for (let i = start; i < end; i++) {
|
|
6
5
|
if (values[i] === needle) return i;
|
|
7
6
|
}
|
|
8
7
|
return -1;
|
|
9
8
|
};
|
|
9
|
+
const __lastIndexOfSingle = (needle, values, bitmap, max, start, end = max) => {
|
|
10
|
+
[start, end] = __clampRange(max, start, end);
|
|
11
|
+
if (bitmap) return bitmap.index.get(needle)?.last(start, end) ?? -1;
|
|
12
|
+
for (let i = end; i-- > start; ) {
|
|
13
|
+
if (values[i] === needle) return i;
|
|
14
|
+
}
|
|
15
|
+
return -1;
|
|
16
|
+
};
|
|
10
17
|
const __indexOfTuple = (needle, values, max, start, end = max) => {
|
|
11
|
-
start =
|
|
12
|
-
end = __clamp(end, 0, max);
|
|
18
|
+
[start, end] = __clampRange(max, start, end);
|
|
13
19
|
if (needle == null) {
|
|
14
20
|
for (let i2 = start; i2 < end; i2++) {
|
|
15
21
|
if (!values[i2]) return i2;
|
|
@@ -29,9 +35,38 @@ const __indexOfTuple = (needle, values, max, start, end = max) => {
|
|
|
29
35
|
}
|
|
30
36
|
return -1;
|
|
31
37
|
};
|
|
38
|
+
const __lastIndexOfTuple = (needle, values, max, start, end = max) => {
|
|
39
|
+
[start, end] = __clampRange(max, start, end);
|
|
40
|
+
if (needle == null) {
|
|
41
|
+
for (let i2 = end; i2-- > start; ) {
|
|
42
|
+
if (!values[i2]) return i2;
|
|
43
|
+
}
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
const n = needle.length;
|
|
47
|
+
let i, j, row;
|
|
48
|
+
outer: for (i = end; i-- > start; ) {
|
|
49
|
+
row = values[i];
|
|
50
|
+
if (row?.length === n) {
|
|
51
|
+
for (j = 0; j < n; j++) {
|
|
52
|
+
if (row[j] !== needle[j]) continue outer;
|
|
53
|
+
}
|
|
54
|
+
return i;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return -1;
|
|
58
|
+
};
|
|
32
59
|
const __clamp = (x, a, b) => x < a ? a : x > b ? b : x;
|
|
60
|
+
const __clampRange = (max, start, end) => {
|
|
61
|
+
start = __clamp(start, 0, max);
|
|
62
|
+
end = __clamp(end ?? max, start, max);
|
|
63
|
+
return [start, end];
|
|
64
|
+
};
|
|
33
65
|
export {
|
|
34
66
|
__clamp,
|
|
67
|
+
__clampRange,
|
|
35
68
|
__indexOfSingle,
|
|
36
|
-
__indexOfTuple
|
|
69
|
+
__indexOfTuple,
|
|
70
|
+
__lastIndexOfSingle,
|
|
71
|
+
__lastIndexOfTuple
|
|
37
72
|
};
|
package/internal/serialize.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export declare const __serializeTyped: ($values: NumericArray, spec: ColumnSpec,
|
|
|
11
11
|
values: any[];
|
|
12
12
|
};
|
|
13
13
|
/** @internal */
|
|
14
|
-
export declare const __deserializeTyped: (type: Type, flags: number, values: number[]) =>
|
|
14
|
+
export declare const __deserializeTyped: (type: Type, flags: number, values: number[]) => Float32Array<ArrayBufferLike> | Float64Array<ArrayBufferLike> | Int8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Uint8ClampedArray<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>;
|
|
15
15
|
//# sourceMappingURL=serialize.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/column-store",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "In-memory column store database with customizable column types, extensible query engine, bitfield indexing for query acceleration, JSON serialization with optional RLE compression",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -126,5 +126,5 @@
|
|
|
126
126
|
"status": "alpha",
|
|
127
127
|
"year": 2025
|
|
128
128
|
},
|
|
129
|
-
"gitHead": "
|
|
129
|
+
"gitHead": "c048d3c6149769309feff3fa943dcd3767b5c6b2\n"
|
|
130
130
|
}
|
package/query.js
CHANGED
|
@@ -3,7 +3,7 @@ import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
|
3
3
|
import { unsupportedOp } from "@thi.ng/errors/unsupported";
|
|
4
4
|
import { Bitfield } from "./bitmap.js";
|
|
5
5
|
import { __columnError } from "./internal/checks.js";
|
|
6
|
-
import {
|
|
6
|
+
import { __clampRange } from "./internal/indexof.js";
|
|
7
7
|
class Query {
|
|
8
8
|
constructor(table, terms = []) {
|
|
9
9
|
this.table = table;
|
|
@@ -302,16 +302,7 @@ const QUERY_OPS = {
|
|
|
302
302
|
if (start != null) $start = column.findIndex((x) => x >= start);
|
|
303
303
|
if (end != null)
|
|
304
304
|
$end = column.findLastIndex((x) => x <= end, $start);
|
|
305
|
-
|
|
306
|
-
const mask = ctx.makeMask();
|
|
307
|
-
const bitmap = new Bitfield(mask);
|
|
308
|
-
bitmap.fill(
|
|
309
|
-
1,
|
|
310
|
-
$start >= 0 ? $start : 0,
|
|
311
|
-
$end >= 0 ? $end + 1 : max
|
|
312
|
-
);
|
|
313
|
-
ctx.mergeMask(mask);
|
|
314
|
-
} else ctx.clear();
|
|
305
|
+
__fillMask(ctx, $start, $end >= 0 ? $end + 1 : $end);
|
|
315
306
|
}
|
|
316
307
|
},
|
|
317
308
|
rowRange: {
|
|
@@ -319,17 +310,19 @@ const QUERY_OPS = {
|
|
|
319
310
|
fn: (ctx, term) => {
|
|
320
311
|
const max = ctx.table.length;
|
|
321
312
|
let { start = 0, end = max } = term.value;
|
|
322
|
-
start =
|
|
323
|
-
|
|
324
|
-
if (start >= 0 && end >= 0) {
|
|
325
|
-
const mask = ctx.makeMask();
|
|
326
|
-
const bitmap = new Bitfield(mask);
|
|
327
|
-
bitmap.fill(1, start, end);
|
|
328
|
-
ctx.mergeMask(mask);
|
|
329
|
-
} else ctx.clear();
|
|
313
|
+
[start, end] = __clampRange(max, start, end);
|
|
314
|
+
__fillMask(ctx, start, end);
|
|
330
315
|
}
|
|
331
316
|
}
|
|
332
317
|
};
|
|
318
|
+
const __fillMask = (ctx, start, end, fill = 1) => {
|
|
319
|
+
if (start >= 0 && end >= 0) {
|
|
320
|
+
const mask = ctx.makeMask();
|
|
321
|
+
const bitmap = new Bitfield(mask);
|
|
322
|
+
bitmap.fill(fill, start, end);
|
|
323
|
+
ctx.mergeMask(mask);
|
|
324
|
+
} else ctx.clear();
|
|
325
|
+
};
|
|
333
326
|
const registerQueryOp = (type, spec) => {
|
|
334
327
|
if (QUERY_OPS[type]) illegalArgs(`query op ${type} already registered`);
|
|
335
328
|
QUERY_OPS[type] = spec;
|
package/table.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export declare class Table<T extends Row> {
|
|
|
33
33
|
getPartialRow<K extends ColumnID<T>>(i: number, columns: K[], safe?: boolean, includeID?: false): Maybe<Pick<T, K>>;
|
|
34
34
|
getPartialRow<K extends ColumnID<T>>(i: number, columns: K[], safe?: boolean, includeID?: true): Maybe<RowWithMeta<Pick<T, K>>>;
|
|
35
35
|
indexOf(id: ColumnID<T>, value: any, start?: number, end?: number): number;
|
|
36
|
+
lastIndexOf(id: ColumnID<T>, value: any, start?: number, end?: number): number;
|
|
36
37
|
validateRow(row: Partial<T>): void;
|
|
37
38
|
validateColumnSpec(id: ColumnID<T>, spec: ColumnSpec): void;
|
|
38
39
|
toJSON(): {
|
package/table.js
CHANGED
|
@@ -105,6 +105,9 @@ class Table {
|
|
|
105
105
|
indexOf(id, value, start, end) {
|
|
106
106
|
return this.columns[id]?.indexOf(value, start, end) ?? -1;
|
|
107
107
|
}
|
|
108
|
+
lastIndexOf(id, value, start, end) {
|
|
109
|
+
return this.columns[id]?.lastIndexOf(value, start, end) ?? -1;
|
|
110
|
+
}
|
|
108
111
|
validateRow(row) {
|
|
109
112
|
const { columns } = this;
|
|
110
113
|
for (let id in columns) {
|