@based/db 0.0.64 → 0.0.67
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 +2 -2
- package/dist/lib/darwin_aarch64/include/selva/colvec.h +71 -0
- package/dist/lib/darwin_aarch64/include/selva/db.h +33 -4
- package/dist/lib/darwin_aarch64/include/selva/fields.h +37 -25
- package/dist/lib/darwin_aarch64/include/selva/hll.h +5 -3
- package/dist/lib/darwin_aarch64/include/selva/membar.h +23 -0
- package/dist/lib/darwin_aarch64/include/selva/types.h +8 -1
- package/dist/lib/darwin_aarch64/include/selva/worker_ctx.h +19 -3
- package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
- package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v24.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
- package/dist/lib/linux_aarch64/include/selva/colvec.h +71 -0
- package/dist/lib/linux_aarch64/include/selva/db.h +33 -4
- package/dist/lib/linux_aarch64/include/selva/fields.h +37 -25
- package/dist/lib/linux_aarch64/include/selva/hll.h +5 -3
- package/dist/lib/linux_aarch64/include/selva/membar.h +23 -0
- package/dist/lib/linux_aarch64/include/selva/types.h +8 -1
- package/dist/lib/linux_aarch64/include/selva/worker_ctx.h +19 -3
- package/dist/lib/linux_aarch64/libjemalloc_selva.so.2 +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v24.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +0 -0
- package/dist/lib/linux_x86_64/include/selva/colvec.h +71 -0
- package/dist/lib/linux_x86_64/include/selva/db.h +33 -4
- package/dist/lib/linux_x86_64/include/selva/fields.h +37 -25
- package/dist/lib/linux_x86_64/include/selva/hll.h +5 -3
- package/dist/lib/linux_x86_64/include/selva/membar.h +23 -0
- package/dist/lib/linux_x86_64/include/selva/types.h +8 -1
- package/dist/lib/linux_x86_64/include/selva/worker_ctx.h +19 -3
- package/dist/lib/linux_x86_64/libjemalloc_selva.so.2 +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v24.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/src/client/flushModify.d.ts +2 -1
- package/dist/src/client/flushModify.js +12 -4
- package/dist/src/client/modify/create.js +11 -0
- package/dist/src/client/modify/delete.js +3 -0
- package/dist/src/client/modify/fixed.js +1 -1
- package/dist/src/client/modify/modify.js +2 -2
- package/dist/src/client/modify/setCursor.d.ts +2 -1
- package/dist/src/client/query/BasedDbQuery.d.ts +10 -4
- package/dist/src/client/query/BasedDbQuery.js +114 -6
- package/dist/src/client/query/aggregates/aggregation.js +24 -11
- package/dist/src/client/query/aggregates/types.d.ts +22 -2
- package/dist/src/client/query/aggregates/types.js +34 -1
- package/dist/src/client/query/display.js +8 -2
- package/dist/src/client/query/filter/createVariableFilterBuffer.d.ts +2 -3
- package/dist/src/client/query/filter/createVariableFilterBuffer.js +20 -7
- package/dist/src/client/query/filter/filter.js +13 -3
- package/dist/src/client/query/filter/primitiveFilter.d.ts +1 -2
- package/dist/src/client/query/include/props.js +18 -2
- package/dist/src/client/query/include/toBuffer.js +11 -3
- package/dist/src/client/query/include/walk.js +5 -1
- package/dist/src/client/query/queryDef.js +4 -1
- package/dist/src/client/query/read/read.js +52 -22
- package/dist/src/client/query/registerQuery.js +1 -0
- package/dist/src/client/query/search/index.d.ts +1 -1
- package/dist/src/client/query/search/index.js +21 -7
- package/dist/src/client/query/sort.d.ts +1 -1
- package/dist/src/client/query/toByteCode/default.d.ts +1 -1
- package/dist/src/client/query/toByteCode/default.js +0 -2
- package/dist/src/client/query/toByteCode/toBuffer.js +0 -7
- package/dist/src/client/query/types.d.ts +16 -5
- package/dist/src/client/query/validation.d.ts +3 -0
- package/dist/src/client/query/validation.js +34 -2
- package/dist/src/client/xxHash64.d.ts +1 -1
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.js +0 -1
- package/dist/src/native.d.ts +7 -4
- package/dist/src/native.js +23 -13
- package/dist/src/server/IoWorker.d.ts +8 -0
- package/dist/src/server/IoWorker.js +39 -0
- package/dist/src/server/QueryWorker.d.ts +8 -0
- package/dist/src/server/QueryWorker.js +26 -0
- package/dist/src/server/blocks.d.ts +24 -0
- package/dist/src/server/blocks.js +112 -0
- package/dist/src/server/dbHash.d.ts +1 -1
- package/dist/src/server/index.d.ts +10 -16
- package/dist/src/server/index.js +39 -15
- package/dist/src/server/migrate/index.d.ts +5 -0
- package/dist/src/server/migrate/index.js +11 -7
- package/dist/src/server/migrate/worker.js +3 -0
- package/dist/src/server/save.d.ts +8 -6
- package/dist/src/server/save.js +34 -78
- package/dist/src/server/schema.js +6 -5
- package/dist/src/server/start.js +57 -60
- package/dist/src/server/tree.d.ts +24 -13
- package/dist/src/server/tree.js +95 -66
- package/dist/src/server/workers/DbWorker.d.ts +17 -0
- package/dist/src/server/{DbWorker.js → workers/DbWorker.js} +15 -17
- package/dist/src/server/workers/io_worker.js +39 -0
- package/dist/src/server/workers/io_worker_types.d.ts +12 -0
- package/dist/src/server/workers/io_worker_types.js +2 -0
- package/dist/src/server/workers/query_worker.d.ts +1 -0
- package/dist/src/server/workers/query_worker.js +4 -0
- package/dist/src/server/workers/worker.d.ts +1 -0
- package/dist/src/server/workers/worker.js +41 -0
- package/dist/src/shared/Emitter.d.ts +1 -0
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.js +1 -1
- package/package.json +3 -3
- package/dist/lib/darwin_aarch64/include/selva/find.h +0 -47
- package/dist/lib/darwin_aarch64/include/selva/history.h +0 -64
- package/dist/lib/darwin_aarch64/include/selva/queue_r.h +0 -190
- package/dist/lib/darwin_aarch64/include/selva/traverse.h +0 -65
- package/dist/lib/linux_aarch64/include/selva/find.h +0 -47
- package/dist/lib/linux_aarch64/include/selva/history.h +0 -64
- package/dist/lib/linux_aarch64/include/selva/queue_r.h +0 -190
- package/dist/lib/linux_aarch64/include/selva/traverse.h +0 -65
- package/dist/lib/linux_x86_64/include/selva/find.h +0 -47
- package/dist/lib/linux_x86_64/include/selva/history.h +0 -64
- package/dist/lib/linux_x86_64/include/selva/queue_r.h +0 -190
- package/dist/lib/linux_x86_64/include/selva/traverse.h +0 -65
- package/dist/src/client/query/serialize.d.ts +0 -4
- package/dist/src/client/query/serialize.js +0 -26
- package/dist/src/server/DbWorker.d.ts +0 -13
- package/dist/src/server/csmt/draw-dot.d.ts +0 -4
- package/dist/src/server/csmt/draw-dot.js +0 -38
- package/dist/src/server/csmt/index.d.ts +0 -4
- package/dist/src/server/csmt/index.js +0 -5
- package/dist/src/server/csmt/match.d.ts +0 -7
- package/dist/src/server/csmt/match.js +0 -10
- package/dist/src/server/csmt/memebership-proof.d.ts +0 -7
- package/dist/src/server/csmt/memebership-proof.js +0 -122
- package/dist/src/server/csmt/tree-utils.d.ts +0 -6
- package/dist/src/server/csmt/tree-utils.js +0 -33
- package/dist/src/server/csmt/tree.d.ts +0 -3
- package/dist/src/server/csmt/tree.js +0 -270
- package/dist/src/server/csmt/types.d.ts +0 -46
- package/dist/src/server/csmt/types.js +0 -2
- package/dist/src/server/worker.js +0 -33
- /package/dist/src/server/{worker.d.ts → workers/io_worker.d.ts} +0 -0
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2024 SAULX
|
|
2
|
+
* Copyright (c) 2024-2025 SAULX
|
|
3
3
|
* SPDX-License-Identifier: MIT
|
|
4
4
|
*/
|
|
5
5
|
#pragma once
|
|
6
6
|
|
|
7
7
|
#include "selva/_export.h"
|
|
8
|
+
#include "libdeflate.h"
|
|
8
9
|
|
|
9
10
|
SELVA_EXPORT
|
|
10
|
-
void worker_ctx_init();
|
|
11
|
+
void worker_ctx_init(void);
|
|
11
12
|
|
|
12
13
|
SELVA_EXPORT
|
|
13
|
-
void worker_ctx_deinit();
|
|
14
|
+
void worker_ctx_deinit(void);
|
|
15
|
+
|
|
16
|
+
SELVA_EXPORT
|
|
17
|
+
enum libdeflate_result worker_ctx_libdeflate_decompress(
|
|
18
|
+
const void *in, size_t in_nbytes,
|
|
19
|
+
void *out, size_t out_nbytes_avail,
|
|
20
|
+
size_t *actual_out_nbytes_ret);
|
|
21
|
+
|
|
22
|
+
SELVA_EXPORT
|
|
23
|
+
enum libdeflate_result worker_ctx_libdeflate_decompress_stream(
|
|
24
|
+
const char *in_buf, size_t in_len,
|
|
25
|
+
libdeflate_decompress_stream_cb_t cb, void *ctx,
|
|
26
|
+
int *result);
|
|
27
|
+
|
|
28
|
+
SELVA_EXPORT
|
|
29
|
+
bool worker_ctx_libdeflate_block_state_growbuf(void);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -7,6 +7,7 @@ export declare class ModifyCtx {
|
|
|
7
7
|
id: number;
|
|
8
8
|
hasSortField: number;
|
|
9
9
|
hasSortText: number;
|
|
10
|
+
hasDefaults: number;
|
|
10
11
|
ctx: {
|
|
11
12
|
queue?: Map<(payload: any) => void, ModifyState>;
|
|
12
13
|
offsets?: Record<number, number>;
|
|
@@ -26,7 +27,7 @@ export declare class ModifyCtx {
|
|
|
26
27
|
markNodeDirty(schema: SchemaTypeDef, nodeId: number): void;
|
|
27
28
|
markTypeDirty(schema: SchemaTypeDef): void;
|
|
28
29
|
updateMax(): void;
|
|
29
|
-
getData(lastIds: Record<number, number>): Uint8Array
|
|
30
|
+
getData(lastIds: Record<number, number>): Uint8Array<ArrayBufferLike>;
|
|
30
31
|
reset(): void;
|
|
31
32
|
}
|
|
32
33
|
export declare const execCtxQueue: (resCtx: ModifyCtx["ctx"], error?: boolean) => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeUint64 } from '@saulx/utils';
|
|
2
2
|
// TODO This definitely shouldn't be copy-pasted here from server/tree.ts
|
|
3
|
-
const
|
|
3
|
+
const makeTreeKeyFromNodeId = (typeId, blockCapacity, nodeId) => {
|
|
4
4
|
const tmp = nodeId - +!(nodeId % blockCapacity);
|
|
5
5
|
return typeId * 4294967296 + ((tmp / blockCapacity) | 0) * blockCapacity + 1;
|
|
6
6
|
};
|
|
@@ -16,6 +16,7 @@ export class ModifyCtx {
|
|
|
16
16
|
id = -1;
|
|
17
17
|
hasSortField = -1;
|
|
18
18
|
hasSortText = -1;
|
|
19
|
+
hasDefaults = -1;
|
|
19
20
|
ctx = {};
|
|
20
21
|
payload;
|
|
21
22
|
max;
|
|
@@ -30,7 +31,7 @@ export class ModifyCtx {
|
|
|
30
31
|
dirtyRanges = new Set();
|
|
31
32
|
dirtyTypes = new Map();
|
|
32
33
|
markNodeDirty(schema, nodeId) {
|
|
33
|
-
const key =
|
|
34
|
+
const key = makeTreeKeyFromNodeId(schema.id, schema.blockCapacity, nodeId);
|
|
34
35
|
if (this.dirtyRanges.has(key)) {
|
|
35
36
|
return;
|
|
36
37
|
}
|
|
@@ -77,9 +78,16 @@ export class ModifyCtx {
|
|
|
77
78
|
data[i++] = lastId >>> 24;
|
|
78
79
|
}
|
|
79
80
|
const view = new DataView(data.buffer, data.byteOffset);
|
|
81
|
+
// this is a problem need to remove these dirtyRanges in general...
|
|
80
82
|
for (let key of this.dirtyRanges) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
if (i < view.byteLength - 8) {
|
|
84
|
+
view.setFloat64(i, key, true);
|
|
85
|
+
i += 8;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.warn('Dirty range does not fit - will remove this', this.dirtyRanges.size, i);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
83
91
|
}
|
|
84
92
|
const lenMinusSchemaHash = this.len - 8;
|
|
85
93
|
data[i++] = lenMinusSchemaHash;
|
|
@@ -52,6 +52,7 @@ const appendCreate = (ctx, def, obj, res, unsafe) => {
|
|
|
52
52
|
ctx.buf.set(def.mainEmpty, ctx.len);
|
|
53
53
|
ctx.len += def.mainLen;
|
|
54
54
|
}
|
|
55
|
+
// add text & string here
|
|
55
56
|
}
|
|
56
57
|
if (def.hasSeperateSort) {
|
|
57
58
|
if (ctx.hasSortField !== def.seperateSort.size - 1) {
|
|
@@ -79,6 +80,16 @@ const appendCreate = (ctx, def, obj, res, unsafe) => {
|
|
|
79
80
|
// add test for this
|
|
80
81
|
ctx.hasSortField = -1;
|
|
81
82
|
}
|
|
83
|
+
// if (def.hasSeperateDefaults) {
|
|
84
|
+
// const buf = def.seperateDefaults.bufferTmp
|
|
85
|
+
// if (ctx.hasDefaults !== def.seperateDefaults.props.size - 1) {
|
|
86
|
+
// //
|
|
87
|
+
// }
|
|
88
|
+
// if (ctx.hasDefaults !== -1) {
|
|
89
|
+
// buf.set(def.seperateTextSort.buffer, 0)
|
|
90
|
+
// }
|
|
91
|
+
// ctx.hasDefaults = -1
|
|
92
|
+
// }
|
|
82
93
|
if (def.hasSeperateTextSort) {
|
|
83
94
|
const buf = def.seperateTextSort.bufferTmp;
|
|
84
95
|
if (ctx.hasSortText !== def.seperateTextSort.size - 1) {
|
|
@@ -8,6 +8,9 @@ export const deleteFn = (db, type, id, opts) => {
|
|
|
8
8
|
if (!def) {
|
|
9
9
|
throw new Error(`Unknown type: ${type}. Did you mean on of: ${Object.keys(db.schemaTypesParsed).join(', ')}`);
|
|
10
10
|
}
|
|
11
|
+
if (def.insertOnly) {
|
|
12
|
+
throw new Error(`This type is insertOnly`);
|
|
13
|
+
}
|
|
11
14
|
const ctx = db.modifyCtx;
|
|
12
15
|
const res = new ModifyState(def.id, id, db, opts);
|
|
13
16
|
const schema = db.schemaTypesParsed[type];
|
|
@@ -98,7 +98,7 @@ map[TIMESTAMP] = (ctx, val, def) => {
|
|
|
98
98
|
ctx.len += 8;
|
|
99
99
|
// Todo use new utils and store as uint64
|
|
100
100
|
view.setFloat64(0, parsedValue, true);
|
|
101
|
-
const ts = view.getFloat64(0)
|
|
101
|
+
// const ts = view.getFloat64(0)
|
|
102
102
|
};
|
|
103
103
|
map[UINT32] = (ctx, val, def) => {
|
|
104
104
|
if (ctx.len + 4 > ctx.max) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPropDef, REFERENCE, REFERENCES, STRING, TEXT, ALIAS, BINARY, CARDINALITY, VECTOR, MICRO_BUFFER, JSON, } from '@based/schema/def';
|
|
1
|
+
import { isPropDef, REFERENCE, REFERENCES, STRING, TEXT, ALIAS, BINARY, CARDINALITY, VECTOR, MICRO_BUFFER, JSON, COLVEC, } from '@based/schema/def';
|
|
2
2
|
import { ModifyError } from './ModifyRes.js';
|
|
3
3
|
import { writeReference } from './references/reference.js';
|
|
4
4
|
import { writeReferences } from './references/references.js';
|
|
@@ -50,7 +50,7 @@ function _modify(ctx, res, obj, schema, mod, tree, overwrite, unsafe) {
|
|
|
50
50
|
else if (type === CARDINALITY) {
|
|
51
51
|
err = writeHll(val, ctx, schema, def, res.tmpId, mod);
|
|
52
52
|
}
|
|
53
|
-
else if (type === VECTOR) {
|
|
53
|
+
else if (type === VECTOR || type === COLVEC) {
|
|
54
54
|
err = writeVector(val, ctx, schema, def, res.tmpId, mod);
|
|
55
55
|
}
|
|
56
56
|
else if (type === JSON) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ModifyCtx } from '../../index.js';
|
|
2
2
|
import { SchemaTypeDef } from '@based/schema/def';
|
|
3
3
|
import { ModifyOp } from './types.js';
|
|
4
|
-
export declare const setCursor: (ctx: ModifyCtx, schema: SchemaTypeDef, field: number,
|
|
4
|
+
export declare const setCursor: (ctx: ModifyCtx, schema: SchemaTypeDef, field: number, // TODO pass propdef better
|
|
5
|
+
typeIndex: number, id: number, modifyOp: ModifyOp, ignoreField?: boolean) => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { QueryDef, QueryTarget, Operator, QueryByAliasObj } from './query.js';
|
|
1
|
+
import { QueryDef, QueryTarget, Operator, QueryByAliasObj, LangFallback } from './query.js';
|
|
2
2
|
import { BasedQueryResponse } from './BasedIterable.js';
|
|
3
3
|
import { Search } from './search/index.js';
|
|
4
|
-
import { OnData, OnError
|
|
4
|
+
import { OnData, OnError } from './subscription/index.js';
|
|
5
5
|
import { DbClient } from '../index.js';
|
|
6
6
|
import { LangName } from '@based/schema';
|
|
7
7
|
import { FilterAst, FilterBranchFn, FilterOpts } from './filter/types.js';
|
|
@@ -25,6 +25,12 @@ export declare class QueryBranch<T> {
|
|
|
25
25
|
groupBy(field: string): T;
|
|
26
26
|
count(field?: string): T;
|
|
27
27
|
sum(...fields: (string | string[])[]): T;
|
|
28
|
+
cardinality(...fields: (string | string[])[]): T;
|
|
29
|
+
stddev(...fields: (string | string[])[]): T;
|
|
30
|
+
var(...fields: (string | string[])[]): T;
|
|
31
|
+
avg(...fields: (string | string[])[]): T;
|
|
32
|
+
max(...fields: (string | string[])[]): T;
|
|
33
|
+
min(...fields: (string | string[])[]): T;
|
|
28
34
|
or(fn: FilterBranchFn): T;
|
|
29
35
|
or(field: string, operator?: Operator | boolean, value?: any, opts?: FilterOpts): T;
|
|
30
36
|
range(start: number, end?: number): T;
|
|
@@ -47,7 +53,7 @@ export declare class BasedDbQuery extends QueryBranch<BasedDbQuery> {
|
|
|
47
53
|
get(): GetPromise;
|
|
48
54
|
buffer: Uint8Array;
|
|
49
55
|
register(): void;
|
|
50
|
-
locale(locale: LangName): this;
|
|
51
|
-
subscribe(onData: OnData, onError?: OnError): OnClose;
|
|
56
|
+
locale(locale: LangName, fallBack?: LangFallback): this;
|
|
57
|
+
subscribe(onData: OnData, onError?: OnError): import("./subscription/types.js").OnClose;
|
|
52
58
|
_getSync(dbCtxExternal: any): BasedQueryResponse;
|
|
53
59
|
}
|
|
@@ -11,6 +11,7 @@ import { langCodesMap } from '@based/schema';
|
|
|
11
11
|
import { convertFilter } from './filter/convertFilter.js';
|
|
12
12
|
import { validateLocale, validateRange } from './validation.js';
|
|
13
13
|
import { DEF_RANGE_PROP_LIMIT } from './thresholds.js';
|
|
14
|
+
import { AggregateType } from './aggregates/types.js';
|
|
14
15
|
import { displayTarget } from './display.js';
|
|
15
16
|
import picocolors from 'picocolors';
|
|
16
17
|
export class QueryBranch {
|
|
@@ -151,7 +152,7 @@ export class QueryBranch {
|
|
|
151
152
|
}
|
|
152
153
|
else {
|
|
153
154
|
const p = field.split('.');
|
|
154
|
-
addAggregate(
|
|
155
|
+
addAggregate(AggregateType.COUNT, this.def, p);
|
|
155
156
|
}
|
|
156
157
|
// @ts-ignore
|
|
157
158
|
return this;
|
|
@@ -167,7 +168,103 @@ export class QueryBranch {
|
|
|
167
168
|
});
|
|
168
169
|
}
|
|
169
170
|
else {
|
|
170
|
-
addAggregate(
|
|
171
|
+
addAggregate(AggregateType.SUM, this.def, fields);
|
|
172
|
+
}
|
|
173
|
+
// @ts-ignore
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
cardinality(...fields) {
|
|
177
|
+
if (fields.length === 0) {
|
|
178
|
+
throw new Error('Empty cardinality() called');
|
|
179
|
+
}
|
|
180
|
+
if (this.queryCommands) {
|
|
181
|
+
this.queryCommands.push({
|
|
182
|
+
method: 'cardinality',
|
|
183
|
+
args: fields,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
addAggregate(AggregateType.CARDINALITY, this.def, fields);
|
|
188
|
+
}
|
|
189
|
+
// @ts-ignore
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
stddev(...fields) {
|
|
193
|
+
if (fields.length === 0) {
|
|
194
|
+
throw new Error('Empty standard deviation function called');
|
|
195
|
+
}
|
|
196
|
+
if (this.queryCommands) {
|
|
197
|
+
this.queryCommands.push({
|
|
198
|
+
method: 'stddev',
|
|
199
|
+
args: fields,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
addAggregate(AggregateType.STDDEV, this.def, fields);
|
|
204
|
+
}
|
|
205
|
+
// @ts-ignore
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
var(...fields) {
|
|
209
|
+
if (fields.length === 0) {
|
|
210
|
+
throw new Error('Empty variance function called');
|
|
211
|
+
}
|
|
212
|
+
if (this.queryCommands) {
|
|
213
|
+
this.queryCommands.push({
|
|
214
|
+
method: 'var',
|
|
215
|
+
args: fields,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
addAggregate(AggregateType.VARIANCE, this.def, fields);
|
|
220
|
+
}
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
return this;
|
|
223
|
+
}
|
|
224
|
+
avg(...fields) {
|
|
225
|
+
if (fields.length === 0) {
|
|
226
|
+
throw new Error('Empty average function called');
|
|
227
|
+
}
|
|
228
|
+
if (this.queryCommands) {
|
|
229
|
+
this.queryCommands.push({
|
|
230
|
+
method: 'avg',
|
|
231
|
+
args: fields,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
addAggregate(AggregateType.AVERAGE, this.def, fields);
|
|
236
|
+
}
|
|
237
|
+
// @ts-ignore
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
240
|
+
max(...fields) {
|
|
241
|
+
if (fields.length === 0) {
|
|
242
|
+
throw new Error('Empty maximum function called');
|
|
243
|
+
}
|
|
244
|
+
if (this.queryCommands) {
|
|
245
|
+
this.queryCommands.push({
|
|
246
|
+
method: 'max',
|
|
247
|
+
args: fields,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
addAggregate(AggregateType.MAX, this.def, fields);
|
|
252
|
+
}
|
|
253
|
+
// @ts-ignore
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
min(...fields) {
|
|
257
|
+
if (fields.length === 0) {
|
|
258
|
+
throw new Error('Empty minimum function called');
|
|
259
|
+
}
|
|
260
|
+
if (this.queryCommands) {
|
|
261
|
+
this.queryCommands.push({
|
|
262
|
+
method: 'min',
|
|
263
|
+
args: fields,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
addAggregate(AggregateType.MIN, this.def, fields);
|
|
171
268
|
}
|
|
172
269
|
// @ts-ignore
|
|
173
270
|
return this;
|
|
@@ -371,16 +468,28 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
371
468
|
register() {
|
|
372
469
|
registerQuery(this);
|
|
373
470
|
}
|
|
374
|
-
locale(locale) {
|
|
471
|
+
locale(locale, fallBack) {
|
|
375
472
|
if (this.queryCommands) {
|
|
376
|
-
this.queryCommands.
|
|
473
|
+
this.queryCommands.unshift({
|
|
377
474
|
method: 'locale',
|
|
378
475
|
args: [locale],
|
|
379
476
|
});
|
|
380
477
|
}
|
|
381
478
|
else {
|
|
479
|
+
if (fallBack === undefined) {
|
|
480
|
+
// Uses fallback from schema if available
|
|
481
|
+
const localeDescriptor = this.def.schema.locales[locale];
|
|
482
|
+
fallBack =
|
|
483
|
+
typeof localeDescriptor === 'object'
|
|
484
|
+
? localeDescriptor.fallback || false
|
|
485
|
+
: false;
|
|
486
|
+
}
|
|
382
487
|
validateLocale(this.def, locale);
|
|
383
|
-
|
|
488
|
+
const fallBackCode = fallBack === false ? [] : [langCodesMap.get(fallBack)];
|
|
489
|
+
this.def.lang = {
|
|
490
|
+
lang: langCodesMap.get(locale) ?? 0,
|
|
491
|
+
fallback: fallBackCode,
|
|
492
|
+
};
|
|
384
493
|
}
|
|
385
494
|
return this;
|
|
386
495
|
}
|
|
@@ -390,7 +499,6 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
390
499
|
onData(res);
|
|
391
500
|
}
|
|
392
501
|
catch (err) {
|
|
393
|
-
// const t = displayTarget(this.def)
|
|
394
502
|
const def = this.def;
|
|
395
503
|
let name = picocolors.red(`QueryError[${displayTarget(def)}]\n`);
|
|
396
504
|
name += ` Error executing onData handler in subscription\n`;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { writeUint16 } from '@saulx/utils';
|
|
2
2
|
import { QueryDefType } from '../types.js';
|
|
3
|
+
import { AggregateType } from './types.js';
|
|
3
4
|
import { UINT32 } from '@based/schema/def';
|
|
4
5
|
import { aggregationFieldDoesNotExist } from '../validation.js';
|
|
6
|
+
import { aggregateTypeMap } from '../aggregates/types.js';
|
|
5
7
|
export const aggregateToBuffer = (aggregates) => {
|
|
6
8
|
const aggBuffer = new Uint8Array(aggregates.size);
|
|
7
9
|
let i = 0;
|
|
@@ -21,7 +23,9 @@ export const aggregateToBuffer = (aggregates) => {
|
|
|
21
23
|
aggBuffer[i] = 0 /* GroupBy.NONE */;
|
|
22
24
|
i += 1;
|
|
23
25
|
}
|
|
24
|
-
writeUint16(aggBuffer, aggregates.
|
|
26
|
+
writeUint16(aggBuffer, aggregates.totalResultsSize, i);
|
|
27
|
+
i += 2;
|
|
28
|
+
writeUint16(aggBuffer, aggregates.totalAccumulatorSize, i);
|
|
25
29
|
i += 2;
|
|
26
30
|
for (const [prop, aggregatesArray] of aggregates.aggregates.entries()) {
|
|
27
31
|
aggBuffer[i] = prop;
|
|
@@ -39,6 +43,8 @@ export const aggregateToBuffer = (aggregates) => {
|
|
|
39
43
|
i += 2;
|
|
40
44
|
writeUint16(aggBuffer, agg.resultPos, i);
|
|
41
45
|
i += 2;
|
|
46
|
+
writeUint16(aggBuffer, agg.accumulatorPos, i);
|
|
47
|
+
i += 2;
|
|
42
48
|
size += i - startI;
|
|
43
49
|
}
|
|
44
50
|
writeUint16(aggBuffer, size, sizeIndex);
|
|
@@ -48,13 +54,13 @@ export const aggregateToBuffer = (aggregates) => {
|
|
|
48
54
|
const ensureAggregate = (def) => {
|
|
49
55
|
if (!def.aggregate) {
|
|
50
56
|
def.aggregate = {
|
|
51
|
-
size:
|
|
57
|
+
size: 5,
|
|
52
58
|
aggregates: new Map(),
|
|
53
|
-
|
|
59
|
+
totalResultsSize: 0,
|
|
60
|
+
totalAccumulatorSize: 0,
|
|
54
61
|
};
|
|
55
62
|
}
|
|
56
63
|
};
|
|
57
|
-
// Group by is great for normal stuff as well (do later)
|
|
58
64
|
export const groupBy = (def, field) => {
|
|
59
65
|
const fieldDef = def.schema.props[field];
|
|
60
66
|
if (!fieldDef) {
|
|
@@ -74,7 +80,7 @@ export const addAggregate = (type, def, fields) => {
|
|
|
74
80
|
addAggregate(type, def, field);
|
|
75
81
|
}
|
|
76
82
|
else {
|
|
77
|
-
const fieldDef = type ===
|
|
83
|
+
const fieldDef = type === AggregateType.COUNT
|
|
78
84
|
? {
|
|
79
85
|
prop: 255,
|
|
80
86
|
path: [field],
|
|
@@ -98,13 +104,20 @@ export const addAggregate = (type, def, fields) => {
|
|
|
98
104
|
aggregateField.push({
|
|
99
105
|
propDef: fieldDef,
|
|
100
106
|
type,
|
|
101
|
-
resultPos: def.aggregate.
|
|
107
|
+
resultPos: def.aggregate.totalResultsSize,
|
|
108
|
+
accumulatorPos: def.aggregate.totalAccumulatorSize,
|
|
102
109
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
110
|
+
const specificSizes = aggregateTypeMap.get(type);
|
|
111
|
+
if (specificSizes) {
|
|
112
|
+
def.aggregate.totalResultsSize += specificSizes.resultsSize;
|
|
113
|
+
def.aggregate.totalAccumulatorSize += specificSizes.accumulatorSize;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
def.aggregate.totalResultsSize += 8;
|
|
117
|
+
def.aggregate.totalAccumulatorSize += 8;
|
|
118
|
+
}
|
|
106
119
|
// needs to add an extra field WRITE TO
|
|
107
|
-
def.aggregate.size +=
|
|
120
|
+
def.aggregate.size += 8;
|
|
108
121
|
}
|
|
109
122
|
}
|
|
110
123
|
};
|
|
@@ -128,7 +141,7 @@ export const isRootCountOnly = (def, filterSize) => {
|
|
|
128
141
|
if (aggs.length !== 1) {
|
|
129
142
|
return false;
|
|
130
143
|
}
|
|
131
|
-
if (aggs[0].type !==
|
|
144
|
+
if (aggs[0].type !== AggregateType.COUNT) {
|
|
132
145
|
return false;
|
|
133
146
|
}
|
|
134
147
|
if (def.filter && def.filter.size > 0) {
|
|
@@ -1,7 +1,27 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare enum AggregateType {
|
|
2
2
|
SUM = 1,
|
|
3
|
-
COUNT = 2
|
|
3
|
+
COUNT = 2,
|
|
4
|
+
CARDINALITY = 3,
|
|
5
|
+
STDDEV = 4,
|
|
6
|
+
AVERAGE = 5,
|
|
7
|
+
VARIANCE = 6,
|
|
8
|
+
MAX = 7,
|
|
9
|
+
MIN = 8
|
|
4
10
|
}
|
|
11
|
+
export declare const enum AccumulatorSize {
|
|
12
|
+
SUM = 8,
|
|
13
|
+
COUNT = 4,
|
|
14
|
+
CARDINALITY = 254,// TODO: accordinly to sparse or dense modes
|
|
15
|
+
STDDEV = 24,// count (u64) + sum (f64) + sum_sq (f64) = 8 + 8 + 8 = 24
|
|
16
|
+
AVERAGE = 16,// count (u64) + sum (f64) = 16
|
|
17
|
+
VARIANCE = 24,// count (u64) + sum (f64) + sum_sq (f64) = 8 + 8 + 8 = 24
|
|
18
|
+
MAX = 8,
|
|
19
|
+
MIN = 8
|
|
20
|
+
}
|
|
21
|
+
export declare const aggregateTypeMap: Map<AggregateType, {
|
|
22
|
+
resultsSize: number;
|
|
23
|
+
accumulatorSize: number;
|
|
24
|
+
}>;
|
|
5
25
|
export declare const enum GroupBy {
|
|
6
26
|
NONE = 0,
|
|
7
27
|
HAS_GROUP = 255
|
|
@@ -1,2 +1,35 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var AggregateType;
|
|
2
|
+
(function (AggregateType) {
|
|
3
|
+
AggregateType[AggregateType["SUM"] = 1] = "SUM";
|
|
4
|
+
AggregateType[AggregateType["COUNT"] = 2] = "COUNT";
|
|
5
|
+
AggregateType[AggregateType["CARDINALITY"] = 3] = "CARDINALITY";
|
|
6
|
+
AggregateType[AggregateType["STDDEV"] = 4] = "STDDEV";
|
|
7
|
+
AggregateType[AggregateType["AVERAGE"] = 5] = "AVERAGE";
|
|
8
|
+
AggregateType[AggregateType["VARIANCE"] = 6] = "VARIANCE";
|
|
9
|
+
AggregateType[AggregateType["MAX"] = 7] = "MAX";
|
|
10
|
+
AggregateType[AggregateType["MIN"] = 8] = "MIN";
|
|
11
|
+
})(AggregateType || (AggregateType = {}));
|
|
12
|
+
export const aggregateTypeMap = new Map([
|
|
13
|
+
[
|
|
14
|
+
AggregateType.CARDINALITY,
|
|
15
|
+
{ resultsSize: 4, accumulatorSize: 254 /* AccumulatorSize.CARDINALITY */ },
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
AggregateType.COUNT,
|
|
19
|
+
{ resultsSize: 4, accumulatorSize: 4 /* AccumulatorSize.COUNT */ },
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
AggregateType.STDDEV,
|
|
23
|
+
{ resultsSize: 8, accumulatorSize: 24 /* AccumulatorSize.STDDEV */ },
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
AggregateType.AVERAGE,
|
|
27
|
+
{ resultsSize: 8, accumulatorSize: 16 /* AccumulatorSize.AVERAGE */ },
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
AggregateType.VARIANCE,
|
|
31
|
+
{ resultsSize: 8, accumulatorSize: 24 /* AccumulatorSize.VARIANCE */ },
|
|
32
|
+
],
|
|
33
|
+
// Othe types like MAX, MIN, SUM fall in the else case in aggregation.ts 8/8
|
|
34
|
+
]);
|
|
2
35
|
//# sourceMappingURL=types.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import picocolors from 'picocolors';
|
|
2
2
|
import { BINARY, CARDINALITY, NUMBER, REFERENCE, REFERENCES, STRING, TEXT, TIMESTAMP, } from '@based/schema/def';
|
|
3
3
|
import { ENCODER } from '@saulx/utils';
|
|
4
|
+
import { AggregateType } from './aggregates/types.js';
|
|
4
5
|
const decimals = (v) => ~~(v * 100) / 100;
|
|
5
6
|
const sizeCalc = (size) => {
|
|
6
7
|
if (size > 1e6) {
|
|
@@ -158,7 +159,10 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
|
|
|
158
159
|
if (typeof v === 'number') {
|
|
159
160
|
if (q.aggregate) {
|
|
160
161
|
str += printNumber(v);
|
|
161
|
-
|
|
162
|
+
// TBD: replace comptime const enum and reverse map it
|
|
163
|
+
const [[__, akv], _] = q.aggregate.aggregates;
|
|
164
|
+
const aggType = akv[0].type;
|
|
165
|
+
str += picocolors.italic(picocolors.dim(` ${AggregateType[aggType].toLowerCase()}`));
|
|
162
166
|
str += ',\n';
|
|
163
167
|
}
|
|
164
168
|
else {
|
|
@@ -219,7 +223,9 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
|
|
|
219
223
|
if (typeof v === 'number') {
|
|
220
224
|
if (q.aggregate) {
|
|
221
225
|
str += printNumber(v);
|
|
222
|
-
|
|
226
|
+
const [[__, akv], _] = q.aggregate.aggregates;
|
|
227
|
+
const aggType = akv[0].type;
|
|
228
|
+
str += picocolors.italic(picocolors.dim(` ${AggregateType[aggType].toLowerCase()}`));
|
|
223
229
|
}
|
|
224
230
|
else {
|
|
225
231
|
str += printNumber(v);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { PropDef, PropDefEdge } from '@based/schema/def';
|
|
2
2
|
import { FilterCtx } from './types.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export declare const createVariableFilterBuffer: (value: any, prop: PropDef | PropDefEdge, ctx: FilterCtx, lang: LangCode) => FilterCondition;
|
|
3
|
+
import { FilterCondition, QueryDef } from '../types.js';
|
|
4
|
+
export declare const createVariableFilterBuffer: (value: any, prop: PropDef | PropDefEdge, ctx: FilterCtx, lang: QueryDef["lang"]) => FilterCondition;
|
|
@@ -33,9 +33,15 @@ const parseValue = (value, prop, ctx, lang) => {
|
|
|
33
33
|
val = ENCODER.encode(val.normalize('NFKD'));
|
|
34
34
|
}
|
|
35
35
|
if (prop.typeIndex === TEXT) {
|
|
36
|
-
|
|
36
|
+
// 1 + size
|
|
37
|
+
const fallbacksSize = lang.lang === 0 ? 0 : lang.fallback.length;
|
|
38
|
+
const tmp = new Uint8Array(val.byteLength + 2 + fallbacksSize);
|
|
37
39
|
tmp.set(val);
|
|
38
|
-
tmp[tmp.byteLength - 1] =
|
|
40
|
+
tmp[tmp.byteLength - 1] = fallbacksSize;
|
|
41
|
+
tmp[tmp.byteLength - 2] = lang.lang;
|
|
42
|
+
for (let i = 0; i < fallbacksSize; i++) {
|
|
43
|
+
tmp[tmp.byteLength - 2 - fallbacksSize + i] = lang.fallback[i];
|
|
44
|
+
}
|
|
39
45
|
val = tmp;
|
|
40
46
|
}
|
|
41
47
|
}
|
|
@@ -90,9 +96,10 @@ export const createVariableFilterBuffer = (value, prop, ctx, lang) => {
|
|
|
90
96
|
prop.typeIndex !== ALIAS &&
|
|
91
97
|
prop.typeIndex !== VECTOR) {
|
|
92
98
|
if (prop.typeIndex === TEXT) {
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const
|
|
99
|
+
const fbLen = 2 + val[val.byteLength - 1];
|
|
100
|
+
const crc = crc32(val.slice(0, -fbLen));
|
|
101
|
+
const len = val.byteLength - fbLen;
|
|
102
|
+
const v = new Uint8Array(8 + fbLen);
|
|
96
103
|
v[0] = crc;
|
|
97
104
|
v[1] = crc >>> 8;
|
|
98
105
|
v[2] = crc >>> 16;
|
|
@@ -101,11 +108,17 @@ export const createVariableFilterBuffer = (value, prop, ctx, lang) => {
|
|
|
101
108
|
v[5] = len >>> 8;
|
|
102
109
|
v[6] = len >>> 16;
|
|
103
110
|
v[7] = len >>> 24;
|
|
104
|
-
|
|
111
|
+
for (let i = 0; i < fbLen; i++) {
|
|
112
|
+
v[v.byteLength - (i + 1)] = val[val.byteLength - (i + 1)];
|
|
113
|
+
}
|
|
105
114
|
parsedCondition = writeVarFilter(mode, v, ctx, prop, 0, 0);
|
|
106
115
|
}
|
|
107
116
|
else {
|
|
108
|
-
parsedCondition = createFixedFilterBuffer(prop, 8, {
|
|
117
|
+
parsedCondition = createFixedFilterBuffer(prop, 8, {
|
|
118
|
+
operation: EQUAL_CRC32,
|
|
119
|
+
type: ctx.type,
|
|
120
|
+
opts: ctx.opts,
|
|
121
|
+
}, val, false);
|
|
109
122
|
}
|
|
110
123
|
}
|
|
111
124
|
else {
|
|
@@ -22,7 +22,11 @@ const referencesFilter = (db, filter, schema, conditions, def) => {
|
|
|
22
22
|
if (edgeDef) {
|
|
23
23
|
conditions.edges ??= new Map();
|
|
24
24
|
size +=
|
|
25
|
-
3 +
|
|
25
|
+
3 +
|
|
26
|
+
primitiveFilter(def, edgeDef, filter, conditions, {
|
|
27
|
+
lang: def.lang.lang,
|
|
28
|
+
fallback: [],
|
|
29
|
+
});
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
}
|
|
@@ -71,12 +75,18 @@ export const filterRaw = (db, filter, schema, conditions, def) => {
|
|
|
71
75
|
filterInvalidLang(def, field);
|
|
72
76
|
return 0;
|
|
73
77
|
}
|
|
74
|
-
return primitiveFilter(def, fieldDef, filter, conditions,
|
|
78
|
+
return primitiveFilter(def, fieldDef, filter, conditions, {
|
|
79
|
+
lang: code,
|
|
80
|
+
fallback: [],
|
|
81
|
+
});
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
if (field === 'id') {
|
|
78
85
|
fieldDef = ID_FIELD_DEF;
|
|
79
|
-
return primitiveFilter(def, fieldDef, filter, conditions,
|
|
86
|
+
return primitiveFilter(def, fieldDef, filter, conditions, {
|
|
87
|
+
lang: def.lang.lang,
|
|
88
|
+
fallback: [], // only fallbacks for this
|
|
89
|
+
});
|
|
80
90
|
}
|
|
81
91
|
return referencesFilter(db, filter, schema, conditions, def);
|
|
82
92
|
}
|