@based/db 0.0.7 → 0.0.9
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 +425 -8
- package/dist/lib/darwin_aarch64/include/selva/db.h +12 -3
- package/dist/lib/darwin_aarch64/include/selva/fields.h +22 -11
- package/dist/lib/darwin_aarch64/include/selva/history.h +49 -0
- package/dist/lib/darwin_aarch64/include/selva/hll.h +21 -0
- package/dist/lib/darwin_aarch64/include/selva/sort.h +14 -0
- package/dist/lib/darwin_aarch64/include/selva/types.h +9 -2
- package/dist/lib/darwin_aarch64/include/selva/vector.h +22 -1
- package/dist/lib/darwin_aarch64/include/selva/xxhash64.h +23 -0
- package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.8.0.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/lib/linux_aarch64/include/selva/db.h +12 -3
- package/dist/lib/linux_aarch64/include/selva/fields.h +22 -11
- package/dist/lib/linux_aarch64/include/selva/history.h +49 -0
- package/dist/lib/linux_aarch64/include/selva/hll.h +21 -0
- package/dist/lib/linux_aarch64/include/selva/sort.h +14 -0
- package/dist/lib/linux_aarch64/include/selva/types.h +9 -2
- package/dist/lib/linux_aarch64/include/selva/vector.h +22 -1
- package/dist/lib/linux_aarch64/include/selva/xxhash64.h +23 -0
- package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +0 -0
- package/dist/lib/linux_x86_64/include/selva/db.h +12 -3
- package/dist/lib/linux_x86_64/include/selva/fields.h +22 -11
- package/dist/lib/linux_x86_64/include/selva/history.h +49 -0
- package/dist/lib/linux_x86_64/include/selva/hll.h +21 -0
- package/dist/lib/linux_x86_64/include/selva/sort.h +14 -0
- package/dist/lib/linux_x86_64/include/selva/types.h +9 -2
- package/dist/lib/linux_x86_64/include/selva/vector.h +22 -1
- package/dist/lib/linux_x86_64/include/selva/xxhash64.h +23 -0
- package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/src/client/bitWise.js +21 -1
- package/dist/src/client/index.d.ts +11 -5
- package/dist/src/client/index.js +57 -11
- package/dist/src/client/modify/ModifyRes.d.ts +4 -1
- package/dist/src/client/modify/ModifyRes.js +8 -1
- package/dist/src/client/modify/alias.js +3 -3
- package/dist/src/client/modify/binary.js +5 -2
- package/dist/src/client/modify/cardinality.d.ts +4 -0
- package/dist/src/client/modify/cardinality.js +50 -0
- package/dist/src/client/modify/create copy.d.ts +5 -0
- package/dist/src/client/modify/create copy.js +112 -0
- package/dist/src/client/modify/create.d.ts +2 -1
- package/dist/src/client/modify/create.js +11 -7
- package/dist/src/client/modify/delete.d.ts +2 -0
- package/dist/src/client/modify/delete.js +37 -0
- package/dist/src/client/modify/expire.d.ts +3 -0
- package/dist/src/client/modify/expire.js +25 -0
- package/dist/src/client/modify/fixed.js +11 -1
- package/dist/src/client/modify/index.d.ts +1 -1
- package/dist/src/client/modify/index.js +1 -1
- package/dist/src/client/modify/json.d.ts +4 -0
- package/dist/src/client/modify/json.js +5 -0
- package/dist/src/client/modify/modify.js +11 -7
- package/dist/src/client/modify/references/edge.js +21 -6
- package/dist/src/client/modify/references/reference.js +2 -2
- package/dist/src/client/modify/references/references.d.ts +0 -1
- package/dist/src/client/modify/references/references.js +4 -4
- package/dist/src/client/modify/remove.d.ts +1 -2
- package/dist/src/client/modify/remove.js +9 -6
- package/dist/src/client/modify/setCursor.d.ts +1 -1
- package/dist/src/client/modify/setCursor.js +4 -1
- package/dist/src/client/modify/string.js +2 -2
- package/dist/src/client/modify/text.d.ts +2 -1
- package/dist/src/client/modify/text.js +13 -7
- package/dist/src/client/modify/types.d.ts +8 -1
- package/dist/src/client/modify/types.js +1 -0
- package/dist/src/client/modify/update.d.ts +2 -1
- package/dist/src/client/modify/update.js +9 -5
- package/dist/src/client/modify/upsert.d.ts +2 -1
- package/dist/src/client/modify/upsert.js +3 -3
- package/dist/src/client/modify/vector copy.d.ts +4 -0
- package/dist/src/client/modify/vector copy.js +46 -0
- package/dist/src/client/modify/vector.js +6 -4
- package/dist/src/client/query/BasedDbQuery.d.ts +4 -3
- package/dist/src/client/query/BasedDbQuery.js +39 -16
- package/dist/src/client/query/BasedIterable.js +3 -3
- package/dist/src/client/query/filter/FilterBranch.d.ts +2 -2
- package/dist/src/client/query/filter/FilterBranch.js +2 -2
- package/dist/src/client/query/filter/createFixedFilterBuffer.d.ts +3 -2
- package/dist/src/client/query/filter/createFixedFilterBuffer.js +14 -11
- package/dist/src/client/query/filter/createReferenceFilter.d.ts +2 -1
- package/dist/src/client/query/filter/createReferenceFilter.js +6 -5
- package/dist/src/client/query/filter/createVariableFilterBuffer.d.ts +2 -1
- package/dist/src/client/query/filter/createVariableFilterBuffer.js +61 -30
- package/dist/src/client/query/filter/filter.d.ts +2 -2
- package/dist/src/client/query/filter/filter.js +27 -22
- package/dist/src/client/query/filter/parseFilterValue.js +9 -64
- package/dist/src/client/query/filter/primitiveFilter.js +7 -11
- package/dist/src/client/query/filter/toBuffer.js +5 -7
- package/dist/src/client/query/filter/types.d.ts +51 -2
- package/dist/src/client/query/filter/types.js +114 -0
- package/dist/src/client/query/include/props.d.ts +2 -0
- package/dist/src/client/query/include/props.js +25 -6
- package/dist/src/client/query/include/toBuffer.js +21 -1
- package/dist/src/client/query/include/walk.js +17 -2
- package/dist/src/client/query/queryDef.js +1 -0
- package/dist/src/client/query/read/read.js +85 -21
- package/dist/src/client/query/search/index.d.ts +2 -0
- package/dist/src/client/query/search/index.js +79 -23
- package/dist/src/client/query/subscription/index.js +2 -2
- package/dist/src/client/query/subscription/markers.d.ts +1 -1
- package/dist/src/client/query/subscription/markers.js +2 -2
- package/dist/src/client/query/toBuffer.js +0 -4
- package/dist/src/client/query/types.d.ts +10 -0
- package/dist/src/client/query/validation.d.ts +3 -2
- package/dist/src/client/query/validation.js +17 -2
- package/dist/src/client/timestamp.d.ts +1 -0
- package/dist/src/client/timestamp.js +68 -0
- package/dist/src/client/xxHash64.d.ts +1 -0
- package/dist/src/client/xxHash64.js +5 -0
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.js +13 -3
- package/dist/src/native.d.ts +1 -0
- package/dist/src/native.js +4 -1
- package/dist/src/server/csmt/tree.js +12 -2
- package/dist/src/server/index.d.ts +12 -4
- package/dist/src/server/index.js +63 -17
- package/dist/src/server/migrate/index.js +6 -2
- package/dist/src/server/migrate/worker.js +3 -3
- package/dist/src/server/schema/selvaBuffer.js +20 -11
- package/dist/src/server/schema/typeDef.d.ts +2 -2
- package/dist/src/server/schema/typeDef.js +14 -5
- package/dist/src/server/schema/types.d.ts +7 -2
- package/dist/src/server/schema/types.js +6 -3
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createQueryDef, QueryDefType, includeFields, filter, sort, defToBuffer,
|
|
1
|
+
import { createQueryDef, QueryDefType, includeFields, filter, sort, defToBuffer, filterOr, convertFilter, isAlias, includeField, } from './query.js';
|
|
2
2
|
import { BasedQueryResponse } from './BasedIterable.js';
|
|
3
3
|
import { createOrGetEdgeRefQueryDef, createOrGetRefQueryDef, } from './include/utils.js';
|
|
4
4
|
import { FilterBranch } from './filter/FilterBranch.js';
|
|
5
|
-
import { search } from './search/index.js';
|
|
6
|
-
import { isValidId, checkMaxIdsPerQuery, checkTotalBufferSize, hasField,
|
|
5
|
+
import { search, vectorSearch } from './search/index.js';
|
|
6
|
+
import { isValidId, checkMaxIdsPerQuery, checkTotalBufferSize, hasField, isValidAlias, } from './validation.js';
|
|
7
7
|
import native from '../../native.js';
|
|
8
8
|
import { REFERENCE, REFERENCES } from '../../server/schema/types.js';
|
|
9
9
|
import { subscribe } from './subscription/index.js';
|
|
@@ -21,13 +21,39 @@ export class QueryBranch {
|
|
|
21
21
|
// @ts-ignore
|
|
22
22
|
return this;
|
|
23
23
|
}
|
|
24
|
-
filter(field, operator, value) {
|
|
25
|
-
const f = convertFilter(field, operator, value);
|
|
24
|
+
filter(field, operator, value, opts) {
|
|
25
|
+
const f = convertFilter(field, operator, value, opts);
|
|
26
26
|
filter(this.db, this.def, f, this.def.filter);
|
|
27
27
|
// @ts-ignore
|
|
28
28
|
return this;
|
|
29
29
|
}
|
|
30
|
-
search(query, ...fields) {
|
|
30
|
+
search(query, field, opts, ...fields) {
|
|
31
|
+
if (ArrayBuffer.isView(query)) {
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
vectorSearch(this.def, query, field, opts ?? {});
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
if (field) {
|
|
38
|
+
if (!fields) {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
fields = [field];
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
fields.unshift(field);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (opts) {
|
|
48
|
+
if (!fields) {
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
fields = [opts];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
fields.unshift(opts);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
31
57
|
if (fields.length) {
|
|
32
58
|
if (fields.length === 1) {
|
|
33
59
|
search(this.def, query, fields[0]);
|
|
@@ -61,14 +87,14 @@ export class QueryBranch {
|
|
|
61
87
|
// @ts-ignore
|
|
62
88
|
return this;
|
|
63
89
|
}
|
|
64
|
-
or(field, operator, value) {
|
|
90
|
+
or(field, operator, value, opts) {
|
|
65
91
|
if (typeof field === 'function') {
|
|
66
92
|
const f = new FilterBranch(this.db, filterOr(this.db, this.def, [], this.def.filter), this.def);
|
|
67
93
|
field(f);
|
|
68
94
|
this.def.filter.size += f.filterBranch.size;
|
|
69
95
|
}
|
|
70
96
|
else {
|
|
71
|
-
const f = convertFilter(field, operator, value);
|
|
97
|
+
const f = convertFilter(field, operator, value, opts);
|
|
72
98
|
filterOr(this.db, this.def, f, this.def.filter);
|
|
73
99
|
}
|
|
74
100
|
// @ts-ignore
|
|
@@ -83,13 +109,7 @@ export class QueryBranch {
|
|
|
83
109
|
include(...fields) {
|
|
84
110
|
for (const f of fields) {
|
|
85
111
|
if (typeof f === 'string') {
|
|
86
|
-
|
|
87
|
-
hasFields(this.def.props);
|
|
88
|
-
includeFields(this.def, getAll(this.def.props));
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
this.def.include.stringFields.add(f);
|
|
92
|
-
}
|
|
112
|
+
includeField(this.def, f);
|
|
93
113
|
}
|
|
94
114
|
else if (typeof f === 'function') {
|
|
95
115
|
f((field) => {
|
|
@@ -122,8 +142,8 @@ export class QueryBranch {
|
|
|
122
142
|
else if (Array.isArray(f)) {
|
|
123
143
|
for (const field of f) {
|
|
124
144
|
hasField(field);
|
|
145
|
+
includeField(this.def, field);
|
|
125
146
|
}
|
|
126
|
-
includeFields(this.def, f);
|
|
127
147
|
}
|
|
128
148
|
else if (f !== undefined) {
|
|
129
149
|
throw new Error('Invalid include statement: expected props, refs and edges (string or array) or function');
|
|
@@ -181,6 +201,9 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
181
201
|
}
|
|
182
202
|
}
|
|
183
203
|
const def = createQueryDef(db, QueryDefType.Root, target);
|
|
204
|
+
if (isAlias(id)) {
|
|
205
|
+
isValidAlias(def, id);
|
|
206
|
+
}
|
|
184
207
|
super(db, def);
|
|
185
208
|
}
|
|
186
209
|
#getInternal = async (resolve, reject) => {
|
|
@@ -2,7 +2,7 @@ import { inspect } from 'node:util';
|
|
|
2
2
|
import picocolors from 'picocolors';
|
|
3
3
|
import { debug, resultToObject, readAllFields } from './query.js';
|
|
4
4
|
import { size, time, inspectData } from './display.js';
|
|
5
|
-
import { readUint32 } from '../bitWise.js';
|
|
5
|
+
import { readFloatLE, readUint32 } from '../bitWise.js';
|
|
6
6
|
export { time, size, inspectData };
|
|
7
7
|
export class BasedQueryResponse {
|
|
8
8
|
result;
|
|
@@ -70,8 +70,8 @@ export class BasedQueryResponse {
|
|
|
70
70
|
id,
|
|
71
71
|
};
|
|
72
72
|
if (this.def.search) {
|
|
73
|
-
item.$searchScore = result
|
|
74
|
-
i +=
|
|
73
|
+
item.$searchScore = readFloatLE(result, i);
|
|
74
|
+
i += 4;
|
|
75
75
|
}
|
|
76
76
|
const l = readAllFields(this.def, result, i, result.byteLength - 4, item, id);
|
|
77
77
|
i += l;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DbClient } from '../../index.js';
|
|
2
2
|
import { QueryDefFilter, QueryDef } from '../types.js';
|
|
3
|
-
import { Operator } from './
|
|
3
|
+
import { FilterOpts, Operator } from './types.js';
|
|
4
4
|
import { FilterBranchFn } from './types.js';
|
|
5
5
|
export declare class FilterBranch {
|
|
6
6
|
constructor(db: DbClient, filterBranch: QueryDefFilter, def: QueryDef);
|
|
@@ -8,6 +8,6 @@ export declare class FilterBranch {
|
|
|
8
8
|
filterBranch: QueryDefFilter;
|
|
9
9
|
def: QueryDef;
|
|
10
10
|
or(fn: FilterBranchFn): FilterBranch;
|
|
11
|
-
or(field: string, operator?: Operator | boolean, value?: any): FilterBranch;
|
|
11
|
+
or(field: string, operator?: Operator | boolean, value?: any, opts?: FilterOpts): FilterBranch;
|
|
12
12
|
filter(field: string, operator?: Operator | boolean, value?: any): this;
|
|
13
13
|
}
|
|
@@ -8,14 +8,14 @@ export class FilterBranch {
|
|
|
8
8
|
db;
|
|
9
9
|
filterBranch;
|
|
10
10
|
def;
|
|
11
|
-
or(field, operator, value) {
|
|
11
|
+
or(field, operator, value, opts) {
|
|
12
12
|
if (typeof field === 'function') {
|
|
13
13
|
const f = new FilterBranch(this.db, filterOr(this.db, this.def, [], this.filterBranch), this.def);
|
|
14
14
|
field(f);
|
|
15
15
|
this.def.filter.size += f.filterBranch.size;
|
|
16
16
|
}
|
|
17
17
|
else {
|
|
18
|
-
const f = convertFilter(field, operator, value);
|
|
18
|
+
const f = convertFilter(field, operator, value, opts);
|
|
19
19
|
filterOr(this.db, this.def, f, this.filterBranch);
|
|
20
20
|
}
|
|
21
21
|
return this;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { PropDef, PropDefEdge } from '../../../server/schema/types.js';
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
2
|
+
import { FilterCtx } from './types.js';
|
|
3
|
+
export declare const writeFixed: (prop: PropDef | PropDefEdge, buf: Buffer, value: any, size: number, offset: number) => void;
|
|
4
|
+
export declare const createFixedFilterBuffer: (prop: PropDef | PropDefEdge, size: number, ctx: FilterCtx, value: any, sort: boolean) => Buffer;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BINARY, STRING, REFERENCES, } from '../../../server/schema/types.js';
|
|
2
2
|
import { propIsSigned } from '../../../server/schema/utils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { EQUAL, MODE_AND_FIXED, MODE_DEFAULT, MODE_OR_FIXED, } from './types.js';
|
|
4
4
|
import { parseFilterValue } from './parseFilterValue.js';
|
|
5
5
|
// -------------------------------------------
|
|
6
6
|
// conditions normal
|
|
@@ -15,7 +15,7 @@ import { parseFilterValue } from './parseFilterValue.js';
|
|
|
15
15
|
// field, [size 2]
|
|
16
16
|
// [or = 2] [size 2] [start 2], [op], [size 2], value[size], [size 2], value[size]
|
|
17
17
|
// -------------------------------------------
|
|
18
|
-
export const writeFixed = (prop, buf, value, size, offset
|
|
18
|
+
export const writeFixed = (prop, buf, value, size, offset) => {
|
|
19
19
|
if (prop.typeIndex === BINARY || prop.typeIndex === STRING) {
|
|
20
20
|
if (typeof value === 'string') {
|
|
21
21
|
const size = buf.write(value, offset + 1, 'utf8');
|
|
@@ -58,18 +58,21 @@ export const writeFixed = (prop, buf, value, size, offset, op) => {
|
|
|
58
58
|
// default = 0,
|
|
59
59
|
// orFixed = 1,
|
|
60
60
|
// orVar = 2,
|
|
61
|
-
export const createFixedFilterBuffer = (prop, size,
|
|
61
|
+
export const createFixedFilterBuffer = (prop, size, ctx, value, sort) => {
|
|
62
62
|
let buf;
|
|
63
63
|
const start = prop.start;
|
|
64
64
|
if (Array.isArray(value)) {
|
|
65
65
|
// [or = 1] [size 2] [start 2] [op], [repeat 2], value[size] value[size] value[size]
|
|
66
66
|
const len = value.length;
|
|
67
67
|
buf = Buffer.allocUnsafe(10 + len * size);
|
|
68
|
-
buf[0] =
|
|
69
|
-
buf[1] =
|
|
68
|
+
buf[0] = ctx.type;
|
|
69
|
+
buf[1] =
|
|
70
|
+
prop.typeIndex === REFERENCES && ctx.operation === EQUAL
|
|
71
|
+
? MODE_AND_FIXED
|
|
72
|
+
: MODE_OR_FIXED;
|
|
70
73
|
buf.writeUInt16LE(size, 2);
|
|
71
74
|
buf.writeUInt16LE(start, 4);
|
|
72
|
-
buf[6] =
|
|
75
|
+
buf[6] = ctx.operation;
|
|
73
76
|
buf[7] = prop.typeIndex;
|
|
74
77
|
buf.writeUInt16LE(len, 8);
|
|
75
78
|
if (sort) {
|
|
@@ -81,20 +84,20 @@ export const createFixedFilterBuffer = (prop, size, op, value, sort) => {
|
|
|
81
84
|
}
|
|
82
85
|
else {
|
|
83
86
|
for (let i = 0; i < len; i++) {
|
|
84
|
-
writeFixed(prop, buf, parseFilterValue(prop, value[i]), size, 10 + i * size
|
|
87
|
+
writeFixed(prop, buf, parseFilterValue(prop, value[i]), size, 10 + i * size);
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
90
|
}
|
|
88
91
|
else {
|
|
89
92
|
// [or = 0] [size 2] [start 2], [op], value[size]
|
|
90
93
|
buf = Buffer.allocUnsafe(8 + size);
|
|
91
|
-
buf[0] =
|
|
92
|
-
buf[1] =
|
|
94
|
+
buf[0] = ctx.type;
|
|
95
|
+
buf[1] = MODE_DEFAULT;
|
|
93
96
|
buf.writeUInt16LE(size, 2);
|
|
94
97
|
buf.writeUInt16LE(start, 4);
|
|
95
|
-
buf[6] =
|
|
98
|
+
buf[6] = ctx.operation;
|
|
96
99
|
buf[7] = prop.typeIndex;
|
|
97
|
-
writeFixed(prop, buf, parseFilterValue(prop, value), size, 8
|
|
100
|
+
writeFixed(prop, buf, parseFilterValue(prop, value), size, 8);
|
|
98
101
|
}
|
|
99
102
|
return buf;
|
|
100
103
|
};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { PropDef, PropDefEdge } from '../../../server/schema/types.js';
|
|
2
|
-
|
|
2
|
+
import { FilterCtx } from './types.js';
|
|
3
|
+
export declare const createReferenceFilter: (prop: PropDef | PropDefEdge, ctx: FilterCtx, value: any) => Buffer;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const createReferenceFilter = (prop,
|
|
1
|
+
import { MODE_REFERENCE } from './types.js';
|
|
2
|
+
export const createReferenceFilter = (prop, ctx, value) => {
|
|
3
3
|
let buf;
|
|
4
4
|
const len = Array.isArray(value) ? value.length : 1;
|
|
5
5
|
buf = Buffer.allocUnsafe(11 + len * 8);
|
|
6
|
-
buf[0] =
|
|
7
|
-
buf[1] =
|
|
6
|
+
buf[0] = ctx.type;
|
|
7
|
+
buf[1] = MODE_REFERENCE;
|
|
8
8
|
buf.writeUInt16LE(8, 2);
|
|
9
9
|
buf.writeUInt16LE(len, 4);
|
|
10
|
-
buf[6] =
|
|
10
|
+
buf[6] = ctx.operation;
|
|
11
11
|
buf[7] = prop.typeIndex;
|
|
12
|
+
// REF TYPE (only 1 exists now...)
|
|
12
13
|
buf[8] = 0;
|
|
13
14
|
buf.writeUInt16LE(prop.inverseTypeId, 9);
|
|
14
15
|
if (Array.isArray(value)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { PropDef, PropDefEdge } from '../../../server/schema/types.js';
|
|
2
|
+
import { FilterCtx } from './types.js';
|
|
2
3
|
import { LangCode } from '@based/schema';
|
|
3
|
-
export declare const createVariableFilterBuffer: (value: any, prop: PropDef | PropDefEdge,
|
|
4
|
+
export declare const createVariableFilterBuffer: (value: any, prop: PropDef | PropDefEdge, ctx: FilterCtx, lang: LangCode) => Buffer;
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
-
import { ALIAS, TEXT, } from '../../../server/schema/types.js';
|
|
2
|
-
import {
|
|
1
|
+
import { ALIAS, TEXT, VECTOR, } from '../../../server/schema/types.js';
|
|
2
|
+
import { EQUAL, EQUAL_CRC32, HAS, HAS_TO_LOWER_CASE, LIKE, MODE_DEFAULT_VAR, MODE_OR_VAR, getVectorFn, } from './types.js';
|
|
3
3
|
import { createFixedFilterBuffer } from './createFixedFilterBuffer.js';
|
|
4
|
-
|
|
4
|
+
import { crc32 } from '../../crc32.js';
|
|
5
|
+
const DEFAULT_SCORE = Buffer.from(new Float32Array([0.5]).buffer);
|
|
6
|
+
const parseValue = (value, prop, ctx, lang) => {
|
|
5
7
|
let val = value;
|
|
6
|
-
if (
|
|
8
|
+
if (ctx.operation === HAS_TO_LOWER_CASE && typeof val === 'string') {
|
|
7
9
|
val = val.toLowerCase();
|
|
8
10
|
}
|
|
11
|
+
if (ctx.operation === LIKE && prop.typeIndex === VECTOR) {
|
|
12
|
+
if (!(val instanceof ArrayBuffer)) {
|
|
13
|
+
throw new Error('Vector should be an arrayBuffer');
|
|
14
|
+
}
|
|
15
|
+
let fn = getVectorFn(ctx.opts.fn);
|
|
16
|
+
const score = ctx.opts.score
|
|
17
|
+
? Buffer.from(new Float32Array([ctx.opts.score]).buffer)
|
|
18
|
+
: DEFAULT_SCORE;
|
|
19
|
+
val = Buffer.concat([Buffer.from(val), Buffer.from([fn]), score]);
|
|
20
|
+
}
|
|
9
21
|
if (val instanceof Uint8Array ||
|
|
10
22
|
typeof value === 'string' ||
|
|
11
23
|
!prop.separate ||
|
|
12
|
-
|
|
24
|
+
ctx.operation !== EQUAL) {
|
|
13
25
|
if (prop.typeIndex === TEXT) {
|
|
14
26
|
// can be optmized replace when using uint8array
|
|
15
27
|
val = Buffer.concat([Buffer.from(val), Buffer.from([lang])]);
|
|
@@ -18,21 +30,29 @@ const parseValue = (value, prop, op, lang) => {
|
|
|
18
30
|
val = Buffer.from(val);
|
|
19
31
|
}
|
|
20
32
|
}
|
|
21
|
-
if (
|
|
22
|
-
|
|
33
|
+
if (val?.BYTES_PER_ELEMENT > 1) {
|
|
34
|
+
val = val.buffer;
|
|
35
|
+
}
|
|
36
|
+
if (!(val instanceof Buffer || val instanceof ArrayBuffer)) {
|
|
37
|
+
throw new Error(`Incorrect value for filter: ${prop.path}`);
|
|
38
|
+
}
|
|
39
|
+
if (ctx.operation === LIKE && prop.typeIndex !== VECTOR) {
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
val = Buffer.concat([val, Buffer.from([ctx.opts.score ?? 2])]);
|
|
23
42
|
}
|
|
43
|
+
// @ts-ignore TODO FDN-576
|
|
24
44
|
return val;
|
|
25
45
|
};
|
|
26
|
-
export const createVariableFilterBuffer = (value, prop,
|
|
27
|
-
let
|
|
46
|
+
export const createVariableFilterBuffer = (value, prop, ctx, lang) => {
|
|
47
|
+
let mode = MODE_DEFAULT_VAR;
|
|
28
48
|
let val;
|
|
29
49
|
let buf;
|
|
30
50
|
if (Array.isArray(value)) {
|
|
31
|
-
if (
|
|
32
|
-
|
|
51
|
+
if (ctx.operation !== EQUAL || !prop.separate) {
|
|
52
|
+
mode = MODE_OR_VAR;
|
|
33
53
|
const x = [];
|
|
34
54
|
for (const v of value) {
|
|
35
|
-
const a = parseValue(v, prop,
|
|
55
|
+
const a = parseValue(v, prop, ctx, lang);
|
|
36
56
|
const size = Buffer.allocUnsafe(2);
|
|
37
57
|
size.writeUint16LE(a.byteLength);
|
|
38
58
|
x.push(size, a);
|
|
@@ -42,49 +62,60 @@ export const createVariableFilterBuffer = (value, prop, op, lang) => {
|
|
|
42
62
|
else {
|
|
43
63
|
const x = [];
|
|
44
64
|
for (const v of value) {
|
|
45
|
-
x.push(parseValue(v, prop,
|
|
65
|
+
x.push(parseValue(v, prop, ctx, lang));
|
|
46
66
|
}
|
|
47
67
|
val = x;
|
|
48
68
|
}
|
|
49
69
|
}
|
|
50
70
|
else {
|
|
51
|
-
val = parseValue(value, prop,
|
|
71
|
+
val = parseValue(value, prop, ctx, lang);
|
|
52
72
|
}
|
|
53
|
-
// --------------------
|
|
54
|
-
if (
|
|
73
|
+
// -------------------- PUT VARIABLES HERE
|
|
74
|
+
if (ctx.operation === EQUAL ||
|
|
75
|
+
ctx.operation === HAS ||
|
|
76
|
+
ctx.operation === LIKE ||
|
|
77
|
+
ctx.operation === HAS_TO_LOWER_CASE) {
|
|
55
78
|
if (prop.separate) {
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
if (ctx.operation === EQUAL &&
|
|
80
|
+
prop.typeIndex !== ALIAS &&
|
|
81
|
+
prop.typeIndex !== VECTOR) {
|
|
82
|
+
if (prop.typeIndex === TEXT) {
|
|
83
|
+
buf = writeVarFilter(mode, Buffer.concat([
|
|
84
|
+
Buffer.from(new Uint32Array([crc32(val.slice(0, -1)), val.byteLength - 1])
|
|
85
|
+
.buffer),
|
|
86
|
+
Buffer.from(new Uint8Array([val[val.length - 1]]).buffer),
|
|
87
|
+
]), ctx, prop, 0, 0);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
buf = createFixedFilterBuffer(prop, 8, { operation: EQUAL_CRC32, type: ctx.type, opts: ctx.opts }, val, false);
|
|
91
|
+
}
|
|
60
92
|
}
|
|
61
93
|
else {
|
|
62
|
-
buf = writeVarFilter(
|
|
94
|
+
buf = writeVarFilter(mode, val, ctx, prop, 0, 0);
|
|
63
95
|
}
|
|
64
96
|
}
|
|
65
97
|
else {
|
|
66
|
-
|
|
67
|
-
buf = writeVarFilter(isOr, val, buf, op, prop, prop.start, prop.len);
|
|
98
|
+
buf = writeVarFilter(mode, val, ctx, prop, prop.start, prop.len);
|
|
68
99
|
}
|
|
69
100
|
}
|
|
70
101
|
else {
|
|
71
|
-
console.log('OP NOT SUPPORTED YET =>',
|
|
102
|
+
console.log('OP NOT SUPPORTED YET =>', ctx);
|
|
72
103
|
}
|
|
73
104
|
return buf;
|
|
74
105
|
};
|
|
75
|
-
function writeVarFilter(
|
|
106
|
+
function writeVarFilter(mode, val, ctx, prop, start, len) {
|
|
76
107
|
const size = val.byteLength;
|
|
77
|
-
buf = Buffer.allocUnsafe(12 + size);
|
|
78
|
-
buf[0] =
|
|
79
|
-
buf[1] =
|
|
108
|
+
const buf = Buffer.allocUnsafe(12 + size);
|
|
109
|
+
buf[0] = ctx.type;
|
|
110
|
+
buf[1] = mode;
|
|
80
111
|
buf.writeUInt16LE(start, 2);
|
|
81
112
|
buf.writeUint16LE(len, 4);
|
|
82
113
|
buf.writeUint32LE(size, 6);
|
|
83
|
-
buf[10] =
|
|
114
|
+
buf[10] = ctx.operation;
|
|
84
115
|
buf[11] = prop.typeIndex;
|
|
85
116
|
// need to pas LANG FROM QUERY
|
|
86
117
|
// need to set on 12 if TEXT
|
|
87
|
-
buf.set(val, 12);
|
|
118
|
+
buf.set(Buffer.from(val), 12);
|
|
88
119
|
return buf;
|
|
89
120
|
}
|
|
90
121
|
//# sourceMappingURL=createVariableFilterBuffer.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { QueryDef, QueryDefFilter } from '../types.js';
|
|
2
2
|
import { SchemaTypeDef } from '../../../server/schema/schema.js';
|
|
3
|
-
import { Operator } from './
|
|
3
|
+
import { FilterOpts, Operator } from './types.js';
|
|
4
4
|
import { Filter, FilterAst } from './types.js';
|
|
5
5
|
import { DbClient } from '../../index.js';
|
|
6
6
|
export { Operator, Filter };
|
|
7
7
|
export declare const filterRaw: (db: DbClient, filter: Filter, schema: SchemaTypeDef, conditions: QueryDefFilter, def: QueryDef) => number;
|
|
8
8
|
export declare const filter: (db: DbClient, def: QueryDef, filterAst: FilterAst, conditions: QueryDefFilter) => void;
|
|
9
9
|
export declare const filterOr: (db: DbClient, def: QueryDef, filterAst: FilterAst[], conditions: QueryDefFilter) => QueryDefFilter;
|
|
10
|
-
export declare const convertFilter: (field: string, operator?: Operator | boolean, value?: any) => FilterAst;
|
|
10
|
+
export declare const convertFilter: (field: string, operator?: Operator | boolean, value?: any, opts?: FilterOpts) => FilterAst;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { isPropDef, ID_FIELD_DEF, TEXT, } from '../../../server/schema/schema.js';
|
|
2
2
|
import { primitiveFilter } from './primitiveFilter.js';
|
|
3
|
+
import { toFilterCtx } from './types.js';
|
|
3
4
|
import { IsFilter } from './types.js';
|
|
4
5
|
import { hasField, checkOperator, checkValue } from '../validation.js';
|
|
5
6
|
import { langCodesMap } from '@based/schema';
|
|
6
7
|
const referencesFilter = (db, filter, schema, conditions, def) => {
|
|
7
|
-
const [fieldStr,
|
|
8
|
+
const [fieldStr, ctx, value] = filter;
|
|
8
9
|
var size = 0;
|
|
9
10
|
const path = fieldStr.split('.');
|
|
10
11
|
let t = schema.tree;
|
|
11
|
-
hasField(fieldStr);
|
|
12
|
-
checkOperator(operator);
|
|
13
|
-
checkValue(value, operator);
|
|
14
12
|
for (let i = 0; i < path.length; i++) {
|
|
15
13
|
const p = path[i];
|
|
16
14
|
t = t[p];
|
|
@@ -45,18 +43,14 @@ const referencesFilter = (db, filter, schema, conditions, def) => {
|
|
|
45
43
|
conditions.references.set(t.prop, refConditions);
|
|
46
44
|
}
|
|
47
45
|
// more nested
|
|
48
|
-
size += filterRaw(db, [path.slice(i + 1).join('.'),
|
|
46
|
+
size += filterRaw(db, [path.slice(i + 1).join('.'), ctx, value], refConditions.schema, refConditions, def);
|
|
49
47
|
return size;
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
|
-
|
|
53
|
-
return size;
|
|
50
|
+
throw new Error(`Query: field "${fieldStr}" does not exist on type ${schema.type}`);
|
|
54
51
|
};
|
|
55
52
|
export const filterRaw = (db, filter, schema, conditions, def) => {
|
|
56
|
-
const
|
|
57
|
-
hasField(field); // Validates if the field is a non-empty string
|
|
58
|
-
checkOperator(operator); // Validates if the operator is valid
|
|
59
|
-
checkValue(value, operator); // Validates the value based on the operator
|
|
53
|
+
const field = filter[0];
|
|
60
54
|
let fieldDef = schema.props[field];
|
|
61
55
|
if (!fieldDef) {
|
|
62
56
|
const s = field.split('.');
|
|
@@ -101,14 +95,14 @@ export const filterOr = (db, def, filterAst, conditions) => {
|
|
|
101
95
|
conditions.size += conditions.or.size;
|
|
102
96
|
return conditions.or;
|
|
103
97
|
};
|
|
104
|
-
|
|
98
|
+
const normalizeNeedle = (s) => {
|
|
105
99
|
return s
|
|
106
100
|
.normalize('NFKD')
|
|
107
101
|
.split('')
|
|
108
102
|
.filter((ch) => ch.charCodeAt(0) <= 127)
|
|
109
103
|
.join('');
|
|
110
|
-
}
|
|
111
|
-
export const convertFilter = (field, operator, value) => {
|
|
104
|
+
};
|
|
105
|
+
export const convertFilter = (field, operator, value, opts) => {
|
|
112
106
|
if (operator === undefined) {
|
|
113
107
|
operator = '=';
|
|
114
108
|
value = true;
|
|
@@ -122,26 +116,37 @@ export const convertFilter = (field, operator, value) => {
|
|
|
122
116
|
checkValue(value, operator);
|
|
123
117
|
if (operator === '!..') {
|
|
124
118
|
return [
|
|
125
|
-
[field, '>', value[1]],
|
|
126
|
-
[field, '<', value[0]],
|
|
119
|
+
[field, toFilterCtx('>', opts), value[1]],
|
|
120
|
+
[field, toFilterCtx('<', opts), value[0]],
|
|
127
121
|
];
|
|
128
122
|
}
|
|
129
123
|
else if (operator === '..') {
|
|
130
124
|
return [
|
|
131
|
-
[field, '>', value[0]],
|
|
132
|
-
[field, '<', value[1]],
|
|
125
|
+
[field, toFilterCtx('>', opts), value[0]],
|
|
126
|
+
[field, toFilterCtx('<', opts), value[1]],
|
|
133
127
|
];
|
|
134
128
|
}
|
|
135
129
|
else {
|
|
136
130
|
if (operator == 'like') {
|
|
137
|
-
if (value
|
|
131
|
+
if (value == null) {
|
|
132
|
+
throw new Error('Value is required');
|
|
133
|
+
}
|
|
134
|
+
if (value?.normalize) {
|
|
138
135
|
value = normalizeNeedle(value);
|
|
139
136
|
}
|
|
140
|
-
else {
|
|
141
|
-
|
|
137
|
+
else if (Array.isArray(value)) {
|
|
138
|
+
if (value[0]?.normalize) {
|
|
139
|
+
value = value.map(normalizeNeedle);
|
|
140
|
+
}
|
|
141
|
+
else if (value[0]?.BYTES_PER_ELEMENT > 1) {
|
|
142
|
+
value = value.map((v) => v.buffer);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (value?.BYTES_PER_ELEMENT > 1) {
|
|
146
|
+
value = value.buffer;
|
|
142
147
|
}
|
|
143
148
|
}
|
|
144
|
-
return [[field, operator, value]];
|
|
149
|
+
return [[field, toFilterCtx(operator, opts), value]];
|
|
145
150
|
}
|
|
146
151
|
};
|
|
147
152
|
//# sourceMappingURL=filter.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { TIMESTAMP, CREATED, UPDATED, ENUM, BOOLEAN, STRING, BINARY, } from '../../../server/schema/types.js';
|
|
1
|
+
import { TIMESTAMP, CREATED, UPDATED, ENUM, BOOLEAN, STRING, BINARY, TEXT, } from '../../../server/schema/types.js';
|
|
2
2
|
import { crc32 } from '../../crc32.js';
|
|
3
|
+
import { convertToTimestamp } from '../../timestamp.js';
|
|
3
4
|
// -------------------------------------------
|
|
4
5
|
// conditions normal
|
|
5
6
|
// field, [size 2]
|
|
@@ -13,26 +14,10 @@ import { crc32 } from '../../crc32.js';
|
|
|
13
14
|
// field, [size 2]
|
|
14
15
|
// [or = 2] [size 2] [start 2], [op], [size 2], value[size], [size 2], value[size]
|
|
15
16
|
// -------------------------------------------
|
|
16
|
-
const timeToNumber = (ex) => {
|
|
17
|
-
if (ex === 's') {
|
|
18
|
-
return 1000;
|
|
19
|
-
}
|
|
20
|
-
if (ex === 'm') {
|
|
21
|
-
return 1000 * 60;
|
|
22
|
-
}
|
|
23
|
-
if (ex === 'h') {
|
|
24
|
-
return 1000 * 60 * 60;
|
|
25
|
-
}
|
|
26
|
-
if (ex === 'd') {
|
|
27
|
-
return 1000 * 60 * 60 * 24;
|
|
28
|
-
}
|
|
29
|
-
if (ex === 'y') {
|
|
30
|
-
return 31556952000;
|
|
31
|
-
}
|
|
32
|
-
return 1;
|
|
33
|
-
};
|
|
34
17
|
export const parseFilterValue = (prop, value) => {
|
|
35
|
-
if (prop.typeIndex === BINARY ||
|
|
18
|
+
if (prop.typeIndex === BINARY ||
|
|
19
|
+
prop.typeIndex === STRING ||
|
|
20
|
+
prop.typeIndex === TEXT) {
|
|
36
21
|
const b = value instanceof Buffer ? value : Buffer.from(value);
|
|
37
22
|
const buf = Buffer.allocUnsafe(8);
|
|
38
23
|
buf.writeUint32LE(crc32(b), 0);
|
|
@@ -48,51 +33,11 @@ export const parseFilterValue = (prop, value) => {
|
|
|
48
33
|
else if (prop.typeIndex === TIMESTAMP ||
|
|
49
34
|
prop.typeIndex === CREATED ||
|
|
50
35
|
prop.typeIndex === UPDATED) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (typeof value === 'string') {
|
|
55
|
-
if (value === 'now') {
|
|
56
|
-
return Date.now();
|
|
57
|
-
}
|
|
58
|
-
const y = value.replace(/([+-])/g, ' $1 ');
|
|
59
|
-
const arr = y.split(/ +/);
|
|
60
|
-
let newValue = 0;
|
|
61
|
-
let now;
|
|
62
|
-
let op = 1;
|
|
63
|
-
for (const seg of arr) {
|
|
64
|
-
if (seg === '-') {
|
|
65
|
-
op = -1;
|
|
66
|
-
}
|
|
67
|
-
else if (seg === '+') {
|
|
68
|
-
op = 1;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
var v = 0;
|
|
72
|
-
if (seg === 'now') {
|
|
73
|
-
if (!now) {
|
|
74
|
-
now = Date.now();
|
|
75
|
-
}
|
|
76
|
-
v = now;
|
|
77
|
-
}
|
|
78
|
-
else if (/[smhdy]$/.test(seg)) {
|
|
79
|
-
const ex = seg[seg.length - 1];
|
|
80
|
-
const number = parseInt(seg, 10);
|
|
81
|
-
v = number * timeToNumber(ex);
|
|
82
|
-
}
|
|
83
|
-
else if (seg) {
|
|
84
|
-
v = new Date(seg).valueOf();
|
|
85
|
-
}
|
|
86
|
-
if (op === -1) {
|
|
87
|
-
newValue -= v;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
newValue += v;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return newValue;
|
|
36
|
+
const v = convertToTimestamp(value);
|
|
37
|
+
if (typeof v !== 'number') {
|
|
38
|
+
throw new Error(`Incorrect value for timestamp ${prop.path.join('.')}`);
|
|
95
39
|
}
|
|
40
|
+
return v;
|
|
96
41
|
}
|
|
97
42
|
return value;
|
|
98
43
|
};
|