@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.
Files changed (144) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/darwin_aarch64/include/selva/colvec.h +71 -0
  3. package/dist/lib/darwin_aarch64/include/selva/db.h +33 -4
  4. package/dist/lib/darwin_aarch64/include/selva/fields.h +37 -25
  5. package/dist/lib/darwin_aarch64/include/selva/hll.h +5 -3
  6. package/dist/lib/darwin_aarch64/include/selva/membar.h +23 -0
  7. package/dist/lib/darwin_aarch64/include/selva/types.h +8 -1
  8. package/dist/lib/darwin_aarch64/include/selva/worker_ctx.h +19 -3
  9. package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
  10. package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
  11. package/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
  12. package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
  13. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  14. package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
  15. package/dist/lib/darwin_aarch64/libnode-v24.node +0 -0
  16. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  17. package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
  18. package/dist/lib/linux_aarch64/include/selva/colvec.h +71 -0
  19. package/dist/lib/linux_aarch64/include/selva/db.h +33 -4
  20. package/dist/lib/linux_aarch64/include/selva/fields.h +37 -25
  21. package/dist/lib/linux_aarch64/include/selva/hll.h +5 -3
  22. package/dist/lib/linux_aarch64/include/selva/membar.h +23 -0
  23. package/dist/lib/linux_aarch64/include/selva/types.h +8 -1
  24. package/dist/lib/linux_aarch64/include/selva/worker_ctx.h +19 -3
  25. package/dist/lib/linux_aarch64/libjemalloc_selva.so.2 +0 -0
  26. package/dist/lib/linux_aarch64/libnode-v20.node +0 -0
  27. package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
  28. package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
  29. package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
  30. package/dist/lib/linux_aarch64/libnode-v24.node +0 -0
  31. package/dist/lib/linux_aarch64/libselva.so +0 -0
  32. package/dist/lib/linux_x86_64/include/selva/colvec.h +71 -0
  33. package/dist/lib/linux_x86_64/include/selva/db.h +33 -4
  34. package/dist/lib/linux_x86_64/include/selva/fields.h +37 -25
  35. package/dist/lib/linux_x86_64/include/selva/hll.h +5 -3
  36. package/dist/lib/linux_x86_64/include/selva/membar.h +23 -0
  37. package/dist/lib/linux_x86_64/include/selva/types.h +8 -1
  38. package/dist/lib/linux_x86_64/include/selva/worker_ctx.h +19 -3
  39. package/dist/lib/linux_x86_64/libjemalloc_selva.so.2 +0 -0
  40. package/dist/lib/linux_x86_64/libnode-v20.node +0 -0
  41. package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
  42. package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
  43. package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
  44. package/dist/lib/linux_x86_64/libnode-v24.node +0 -0
  45. package/dist/lib/linux_x86_64/libselva.so +0 -0
  46. package/dist/src/client/flushModify.d.ts +2 -1
  47. package/dist/src/client/flushModify.js +12 -4
  48. package/dist/src/client/modify/create.js +11 -0
  49. package/dist/src/client/modify/delete.js +3 -0
  50. package/dist/src/client/modify/fixed.js +1 -1
  51. package/dist/src/client/modify/modify.js +2 -2
  52. package/dist/src/client/modify/setCursor.d.ts +2 -1
  53. package/dist/src/client/query/BasedDbQuery.d.ts +10 -4
  54. package/dist/src/client/query/BasedDbQuery.js +114 -6
  55. package/dist/src/client/query/aggregates/aggregation.js +24 -11
  56. package/dist/src/client/query/aggregates/types.d.ts +22 -2
  57. package/dist/src/client/query/aggregates/types.js +34 -1
  58. package/dist/src/client/query/display.js +8 -2
  59. package/dist/src/client/query/filter/createVariableFilterBuffer.d.ts +2 -3
  60. package/dist/src/client/query/filter/createVariableFilterBuffer.js +20 -7
  61. package/dist/src/client/query/filter/filter.js +13 -3
  62. package/dist/src/client/query/filter/primitiveFilter.d.ts +1 -2
  63. package/dist/src/client/query/include/props.js +18 -2
  64. package/dist/src/client/query/include/toBuffer.js +11 -3
  65. package/dist/src/client/query/include/walk.js +5 -1
  66. package/dist/src/client/query/queryDef.js +4 -1
  67. package/dist/src/client/query/read/read.js +52 -22
  68. package/dist/src/client/query/registerQuery.js +1 -0
  69. package/dist/src/client/query/search/index.d.ts +1 -1
  70. package/dist/src/client/query/search/index.js +21 -7
  71. package/dist/src/client/query/sort.d.ts +1 -1
  72. package/dist/src/client/query/toByteCode/default.d.ts +1 -1
  73. package/dist/src/client/query/toByteCode/default.js +0 -2
  74. package/dist/src/client/query/toByteCode/toBuffer.js +0 -7
  75. package/dist/src/client/query/types.d.ts +16 -5
  76. package/dist/src/client/query/validation.d.ts +3 -0
  77. package/dist/src/client/query/validation.js +34 -2
  78. package/dist/src/client/xxHash64.d.ts +1 -1
  79. package/dist/src/index.d.ts +1 -2
  80. package/dist/src/index.js +0 -1
  81. package/dist/src/native.d.ts +7 -4
  82. package/dist/src/native.js +23 -13
  83. package/dist/src/server/IoWorker.d.ts +8 -0
  84. package/dist/src/server/IoWorker.js +39 -0
  85. package/dist/src/server/QueryWorker.d.ts +8 -0
  86. package/dist/src/server/QueryWorker.js +26 -0
  87. package/dist/src/server/blocks.d.ts +24 -0
  88. package/dist/src/server/blocks.js +112 -0
  89. package/dist/src/server/dbHash.d.ts +1 -1
  90. package/dist/src/server/index.d.ts +10 -16
  91. package/dist/src/server/index.js +39 -15
  92. package/dist/src/server/migrate/index.d.ts +5 -0
  93. package/dist/src/server/migrate/index.js +11 -7
  94. package/dist/src/server/migrate/worker.js +3 -0
  95. package/dist/src/server/save.d.ts +8 -6
  96. package/dist/src/server/save.js +34 -78
  97. package/dist/src/server/schema.js +6 -5
  98. package/dist/src/server/start.js +57 -60
  99. package/dist/src/server/tree.d.ts +24 -13
  100. package/dist/src/server/tree.js +95 -66
  101. package/dist/src/server/workers/DbWorker.d.ts +17 -0
  102. package/dist/src/server/{DbWorker.js → workers/DbWorker.js} +15 -17
  103. package/dist/src/server/workers/io_worker.js +39 -0
  104. package/dist/src/server/workers/io_worker_types.d.ts +12 -0
  105. package/dist/src/server/workers/io_worker_types.js +2 -0
  106. package/dist/src/server/workers/query_worker.d.ts +1 -0
  107. package/dist/src/server/workers/query_worker.js +4 -0
  108. package/dist/src/server/workers/worker.d.ts +1 -0
  109. package/dist/src/server/workers/worker.js +41 -0
  110. package/dist/src/shared/Emitter.d.ts +1 -0
  111. package/dist/src/types.d.ts +1 -1
  112. package/dist/src/types.js +1 -1
  113. package/package.json +3 -3
  114. package/dist/lib/darwin_aarch64/include/selva/find.h +0 -47
  115. package/dist/lib/darwin_aarch64/include/selva/history.h +0 -64
  116. package/dist/lib/darwin_aarch64/include/selva/queue_r.h +0 -190
  117. package/dist/lib/darwin_aarch64/include/selva/traverse.h +0 -65
  118. package/dist/lib/linux_aarch64/include/selva/find.h +0 -47
  119. package/dist/lib/linux_aarch64/include/selva/history.h +0 -64
  120. package/dist/lib/linux_aarch64/include/selva/queue_r.h +0 -190
  121. package/dist/lib/linux_aarch64/include/selva/traverse.h +0 -65
  122. package/dist/lib/linux_x86_64/include/selva/find.h +0 -47
  123. package/dist/lib/linux_x86_64/include/selva/history.h +0 -64
  124. package/dist/lib/linux_x86_64/include/selva/queue_r.h +0 -190
  125. package/dist/lib/linux_x86_64/include/selva/traverse.h +0 -65
  126. package/dist/src/client/query/serialize.d.ts +0 -4
  127. package/dist/src/client/query/serialize.js +0 -26
  128. package/dist/src/server/DbWorker.d.ts +0 -13
  129. package/dist/src/server/csmt/draw-dot.d.ts +0 -4
  130. package/dist/src/server/csmt/draw-dot.js +0 -38
  131. package/dist/src/server/csmt/index.d.ts +0 -4
  132. package/dist/src/server/csmt/index.js +0 -5
  133. package/dist/src/server/csmt/match.d.ts +0 -7
  134. package/dist/src/server/csmt/match.js +0 -10
  135. package/dist/src/server/csmt/memebership-proof.d.ts +0 -7
  136. package/dist/src/server/csmt/memebership-proof.js +0 -122
  137. package/dist/src/server/csmt/tree-utils.d.ts +0 -6
  138. package/dist/src/server/csmt/tree-utils.js +0 -33
  139. package/dist/src/server/csmt/tree.d.ts +0 -3
  140. package/dist/src/server/csmt/tree.js +0 -270
  141. package/dist/src/server/csmt/types.d.ts +0 -46
  142. package/dist/src/server/csmt/types.js +0 -2
  143. package/dist/src/server/worker.js +0 -33
  144. /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
@@ -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 makeCsmtKeyFromNodeId = (typeId, blockCapacity, nodeId) => {
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 = makeCsmtKeyFromNodeId(schema.id, schema.blockCapacity, nodeId);
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
- view.setFloat64(i, key, true);
82
- i += 8;
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, typeIndex: number, id: number, modifyOp: ModifyOp, ignoreField?: boolean) => void;
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, OnClose } from './subscription/index.js';
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(2 /* AggregateType.COUNT */, this.def, p);
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(1 /* AggregateType.SUM */, this.def, fields);
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.push({
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
- this.def.lang = langCodesMap.get(locale) ?? 0;
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.totalResultsPos, i);
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: 3,
57
+ size: 5,
52
58
  aggregates: new Map(),
53
- totalResultsPos: 0,
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 === 2 /* AggregateType.COUNT */
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.totalResultsPos,
107
+ resultPos: def.aggregate.totalResultsSize,
108
+ accumulatorPos: def.aggregate.totalAccumulatorSize,
102
109
  });
103
- // IF FLOAT // NUMBER ETC USE 8!
104
- // do this better
105
- def.aggregate.totalResultsPos += 4;
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 += 6;
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 !== 2 /* AggregateType.COUNT */) {
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 const enum AggregateType {
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
- str += picocolors.italic(picocolors.dim(` ${key.indexOf('count') >= 0 ? ' count' : ' sum'}`));
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
- str += picocolors.italic(picocolors.dim(` ${key.indexOf('count') >= 0 ? ' count' : ' sum'}`));
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 { LangCode } from '@based/schema';
4
- import { FilterCondition } from '../types.js';
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
- const tmp = new Uint8Array(val.byteLength + 1);
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] = lang;
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 crc = crc32(val.slice(0, -1));
94
- const len = val.byteLength - 1;
95
- const v = new Uint8Array(9);
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
- v[8] = val[val.length - 1];
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, { operation: EQUAL_CRC32, type: ctx.type, opts: ctx.opts }, val, false);
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 + primitiveFilter(def, edgeDef, filter, conditions, def.lang);
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, code);
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, def.lang);
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
  }