@nicia-ai/typegraph 0.20.0 → 0.22.0
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/dist/{ast-Bh2NDeaK.d.cts → ast-CSLbPIOC.d.ts} +56 -3
- package/dist/{ast-COMyNeMn.d.ts → ast-DogwbBqA.d.cts} +56 -3
- package/dist/backend/postgres/index.cjs +123 -45
- package/dist/backend/postgres/index.cjs.map +1 -1
- package/dist/backend/postgres/index.d.cts +15 -7
- package/dist/backend/postgres/index.d.ts +15 -7
- package/dist/backend/postgres/index.js +101 -23
- package/dist/backend/postgres/index.js.map +1 -1
- package/dist/backend/sqlite/index.cjs +15 -15
- package/dist/backend/sqlite/index.d.cts +22 -7
- package/dist/backend/sqlite/index.d.ts +22 -7
- package/dist/backend/sqlite/index.js +5 -5
- package/dist/backend/sqlite/libsql.cjs +8 -8
- package/dist/backend/sqlite/libsql.d.cts +4 -5
- package/dist/backend/sqlite/libsql.d.ts +4 -5
- package/dist/backend/sqlite/libsql.js +5 -5
- package/dist/backend/sqlite/local.cjs +27 -10
- package/dist/backend/sqlite/local.cjs.map +1 -1
- package/dist/backend/sqlite/local.d.cts +4 -5
- package/dist/backend/sqlite/local.d.ts +4 -5
- package/dist/backend/sqlite/local.js +22 -6
- package/dist/backend/sqlite/local.js.map +1 -1
- package/dist/{chunk-MME3H4ZF.cjs → chunk-3JK66E3I.cjs} +387 -9
- package/dist/chunk-3JK66E3I.cjs.map +1 -0
- package/dist/{chunk-6GWJH6AR.js → chunk-3PPEHLGK.js} +4 -4
- package/dist/{chunk-6GWJH6AR.js.map → chunk-3PPEHLGK.js.map} +1 -1
- package/dist/{chunk-QFZQGEQ3.js → chunk-5ZMMHUWR.js} +199 -38
- package/dist/chunk-5ZMMHUWR.js.map +1 -0
- package/dist/{chunk-GNIYZKBI.js → chunk-753F33CV.js} +378 -8
- package/dist/chunk-753F33CV.js.map +1 -0
- package/dist/{chunk-K7SQ3SWP.js → chunk-EYELZHKY.js} +120 -12
- package/dist/chunk-EYELZHKY.js.map +1 -0
- package/dist/{chunk-HXJXTOXR.cjs → chunk-GUYI6VAS.cjs} +101 -21
- package/dist/chunk-GUYI6VAS.cjs.map +1 -0
- package/dist/{chunk-X33WV2UF.cjs → chunk-HRNQ3DVJ.cjs} +24 -21
- package/dist/chunk-HRNQ3DVJ.cjs.map +1 -0
- package/dist/{chunk-W6M7XWKX.js → chunk-JYUQA77I.js} +21 -18
- package/dist/chunk-JYUQA77I.js.map +1 -0
- package/dist/{chunk-LLHFS53Q.js → chunk-NSLTDXVH.js} +91 -11
- package/dist/chunk-NSLTDXVH.js.map +1 -0
- package/dist/{chunk-LELLOHJK.cjs → chunk-PEE4EWXZ.cjs} +35 -35
- package/dist/{chunk-LELLOHJK.cjs.map → chunk-PEE4EWXZ.cjs.map} +1 -1
- package/dist/{chunk-G5CYWKRF.js → chunk-RS5OLGEW.js} +2 -2
- package/dist/{chunk-G5CYWKRF.js.map → chunk-RS5OLGEW.js.map} +1 -1
- package/dist/{chunk-IYWWXOVK.cjs → chunk-SCXOGKLD.cjs} +252 -91
- package/dist/chunk-SCXOGKLD.cjs.map +1 -0
- package/dist/{chunk-P5CNM325.cjs → chunk-UVZHTBZ5.cjs} +123 -11
- package/dist/chunk-UVZHTBZ5.cjs.map +1 -0
- package/dist/{chunk-5GZMPJOP.cjs → chunk-WRWVWKQL.cjs} +2 -2
- package/dist/{chunk-5GZMPJOP.cjs.map → chunk-WRWVWKQL.cjs.map} +1 -1
- package/dist/{ddl-BBo2EcFc.d.cts → ddl-BqkTShcR.d.ts} +28 -6
- package/dist/{ddl-D4jlcOH_.d.ts → ddl-Dk1NDN3M.d.cts} +28 -6
- package/dist/index.cjs +1809 -513
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -11
- package/dist/index.d.ts +53 -11
- package/dist/index.js +1668 -398
- package/dist/index.js.map +1 -1
- package/dist/indexes/index.cjs +17 -17
- package/dist/indexes/index.d.cts +5 -5
- package/dist/indexes/index.d.ts +5 -5
- package/dist/indexes/index.js +3 -3
- package/dist/interchange/index.cjs +6 -6
- package/dist/interchange/index.d.cts +4 -5
- package/dist/interchange/index.d.ts +4 -5
- package/dist/interchange/index.js +1 -1
- package/dist/{manager-Chhrq1vl.d.ts → manager-0jVZtiE8.d.ts} +1 -2
- package/dist/{manager-Bj1UEnhE.d.cts → manager-BPK-2PUI.d.cts} +1 -2
- package/dist/profiler/index.cjs +15 -8
- package/dist/profiler/index.cjs.map +1 -1
- package/dist/profiler/index.d.cts +7 -8
- package/dist/profiler/index.d.ts +7 -8
- package/dist/profiler/index.js +8 -1
- package/dist/profiler/index.js.map +1 -1
- package/dist/schema/index.cjs +21 -21
- package/dist/schema/index.d.cts +4 -5
- package/dist/schema/index.d.ts +4 -5
- package/dist/schema/index.js +3 -3
- package/dist/{sqlite-DE-6NWtC.d.cts → sqlite-D1rrwcir.d.cts} +14 -1
- package/dist/{sqlite-Blq-AhmK.d.ts → sqlite-W3rmJMlc.d.ts} +14 -1
- package/dist/{store-BMrRi_mY.d.ts → store-2QW2SIRk.d.cts} +404 -5
- package/dist/{store-DRRvALu8.d.cts → store-C0q13mtJ.d.ts} +404 -5
- package/dist/{types-B3mmOMJV.d.cts → types-CQF88McG.d.cts} +475 -2
- package/dist/{types-ThB4cFLp.d.ts → types-CQF88McG.d.ts} +475 -2
- package/dist/{types-COPePE8_.d.ts → types-CglvhPKz.d.ts} +1 -1
- package/dist/{types-CVtGFpB9.d.cts → types-D23slCOA.d.cts} +1 -1
- package/dist/{types-Ceb01czq.d.ts → types-IMQCuser.d.ts} +2 -2
- package/dist/{types-CZd2PEOc.d.cts → types-vgjar7Ch.d.cts} +2 -2
- package/package.json +9 -9
- package/dist/chunk-GNIYZKBI.js.map +0 -1
- package/dist/chunk-HXJXTOXR.cjs.map +0 -1
- package/dist/chunk-IYWWXOVK.cjs.map +0 -1
- package/dist/chunk-K7SQ3SWP.js.map +0 -1
- package/dist/chunk-LLHFS53Q.js.map +0 -1
- package/dist/chunk-MME3H4ZF.cjs.map +0 -1
- package/dist/chunk-P5CNM325.cjs.map +0 -1
- package/dist/chunk-QFZQGEQ3.js.map +0 -1
- package/dist/chunk-W6M7XWKX.js.map +0 -1
- package/dist/chunk-X33WV2UF.cjs.map +0 -1
- package/dist/types-DMzKq0d5.d.cts +0 -181
- package/dist/types-DMzKq0d5.d.ts +0 -181
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkHRNQ3DVJ_cjs = require('./chunk-HRNQ3DVJ.cjs');
|
|
4
|
+
var chunkWRWVWKQL_cjs = require('./chunk-WRWVWKQL.cjs');
|
|
5
5
|
var chunkO5PST6TB_cjs = require('./chunk-O5PST6TB.cjs');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var chunk3JK66E3I_cjs = require('./chunk-3JK66E3I.cjs');
|
|
7
|
+
var chunkUVZHTBZ5_cjs = require('./chunk-UVZHTBZ5.cjs');
|
|
8
8
|
var zod = require('zod');
|
|
9
9
|
var drizzleOrm = require('drizzle-orm');
|
|
10
10
|
var nanoid = require('nanoid');
|
|
@@ -29,6 +29,44 @@ var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
|
|
|
29
29
|
"constructor",
|
|
30
30
|
"prototype"
|
|
31
31
|
]);
|
|
32
|
+
var RESERVED_PROPERTY_PREFIX = "$";
|
|
33
|
+
function isReservedPropertyName(name) {
|
|
34
|
+
return name.startsWith(RESERVED_PROPERTY_PREFIX);
|
|
35
|
+
}
|
|
36
|
+
function assertSchemaKeysAreFree(entityKind, name, keys, reservedStructuralKeys) {
|
|
37
|
+
const structuralConflicts = keys.filter(
|
|
38
|
+
(key) => reservedStructuralKeys.has(key)
|
|
39
|
+
);
|
|
40
|
+
if (structuralConflicts.length > 0) {
|
|
41
|
+
const label = entityKind.toLowerCase();
|
|
42
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
43
|
+
`${entityKind} "${name}" schema contains reserved property names: ${structuralConflicts.join(", ")}`,
|
|
44
|
+
{
|
|
45
|
+
[`${label}Type`]: name,
|
|
46
|
+
conflicts: structuralConflicts,
|
|
47
|
+
reservedKeys: [...reservedStructuralKeys]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
suggestion: `Rename the conflicting properties. Reserved names (${[...reservedStructuralKeys].join(", ")}) are added automatically to all ${label}s.`
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const prefixConflicts = keys.filter((key) => isReservedPropertyName(key));
|
|
55
|
+
if (prefixConflicts.length > 0) {
|
|
56
|
+
const label = entityKind.toLowerCase();
|
|
57
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
58
|
+
`${entityKind} "${name}" schema uses the reserved "${RESERVED_PROPERTY_PREFIX}" prefix on: ${prefixConflicts.join(", ")}`,
|
|
59
|
+
{
|
|
60
|
+
[`${label}Type`]: name,
|
|
61
|
+
conflicts: prefixConflicts,
|
|
62
|
+
reservedPrefix: RESERVED_PROPERTY_PREFIX
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
suggestion: `Property names starting with "${RESERVED_PROPERTY_PREFIX}" are reserved for TypeGraph accessors (e.g. $fulltext). Rename each field.`
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
32
70
|
function validateProjectionField(field2, entityType, kind) {
|
|
33
71
|
const reserved = entityType === "node" ? RESERVED_NODE_KEYS : RESERVED_EDGE_KEYS;
|
|
34
72
|
if (reserved.has(field2)) {
|
|
@@ -62,24 +100,17 @@ function filterReservedKeys(props, reservedKeys) {
|
|
|
62
100
|
|
|
63
101
|
// src/core/node.ts
|
|
64
102
|
function validateSchemaKeys(schema, name) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
103
|
+
assertSchemaKeysAreFree(
|
|
104
|
+
"Node",
|
|
105
|
+
name,
|
|
106
|
+
Object.keys(schema.shape),
|
|
107
|
+
RESERVED_NODE_KEYS
|
|
68
108
|
);
|
|
69
|
-
if (conflicts.length > 0) {
|
|
70
|
-
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
71
|
-
`Node "${name}" schema contains reserved property names: ${conflicts.join(", ")}`,
|
|
72
|
-
{ nodeType: name, conflicts, reservedKeys: [...RESERVED_NODE_KEYS] },
|
|
73
|
-
{
|
|
74
|
-
suggestion: `Rename the conflicting properties. Reserved names (id, kind, meta) are added automatically to all nodes.`
|
|
75
|
-
}
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
109
|
}
|
|
79
110
|
function defineNode(name, options) {
|
|
80
111
|
validateSchemaKeys(options.schema, name);
|
|
81
112
|
return Object.freeze({
|
|
82
|
-
[
|
|
113
|
+
[chunkWRWVWKQL_cjs.NODE_TYPE_BRAND]: true,
|
|
83
114
|
kind: name,
|
|
84
115
|
schema: options.schema,
|
|
85
116
|
description: options.description
|
|
@@ -87,25 +118,18 @@ function defineNode(name, options) {
|
|
|
87
118
|
}
|
|
88
119
|
var EMPTY_SCHEMA = zod.z.object({});
|
|
89
120
|
function validateSchemaKeys2(schema, name) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
121
|
+
assertSchemaKeysAreFree(
|
|
122
|
+
"Edge",
|
|
123
|
+
name,
|
|
124
|
+
Object.keys(schema.shape),
|
|
125
|
+
RESERVED_EDGE_KEYS
|
|
93
126
|
);
|
|
94
|
-
if (conflicts.length > 0) {
|
|
95
|
-
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
96
|
-
`Edge "${name}" schema contains reserved property names: ${conflicts.join(", ")}`,
|
|
97
|
-
{ edgeType: name, conflicts, reservedKeys: [...RESERVED_EDGE_KEYS] },
|
|
98
|
-
{
|
|
99
|
-
suggestion: `Rename the conflicting properties. Reserved names are added automatically to all edges.`
|
|
100
|
-
}
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
127
|
}
|
|
104
128
|
function defineEdge(name, options) {
|
|
105
129
|
const schema = options?.schema ?? EMPTY_SCHEMA;
|
|
106
130
|
validateSchemaKeys2(schema, name);
|
|
107
131
|
return Object.freeze({
|
|
108
|
-
[
|
|
132
|
+
[chunkWRWVWKQL_cjs.EDGE_TYPE_BRAND]: true,
|
|
109
133
|
kind: name,
|
|
110
134
|
schema,
|
|
111
135
|
description: options?.description,
|
|
@@ -125,7 +149,7 @@ function metaEdge(name, options = {}) {
|
|
|
125
149
|
description: options.description
|
|
126
150
|
};
|
|
127
151
|
return Object.freeze({
|
|
128
|
-
[
|
|
152
|
+
[chunkHRNQ3DVJ_cjs.META_EDGE_BRAND]: true,
|
|
129
153
|
name,
|
|
130
154
|
properties
|
|
131
155
|
});
|
|
@@ -161,7 +185,7 @@ function createExternalRef(table) {
|
|
|
161
185
|
// src/ontology/core-meta-edges.ts
|
|
162
186
|
function createMetaEdge(name, properties) {
|
|
163
187
|
return Object.freeze({
|
|
164
|
-
[
|
|
188
|
+
[chunkHRNQ3DVJ_cjs.META_EDGE_BRAND]: true,
|
|
165
189
|
name,
|
|
166
190
|
properties: {
|
|
167
191
|
transitive: properties.transitive ?? false,
|
|
@@ -173,7 +197,7 @@ function createMetaEdge(name, properties) {
|
|
|
173
197
|
}
|
|
174
198
|
});
|
|
175
199
|
}
|
|
176
|
-
var subClassOfMetaEdge = createMetaEdge(
|
|
200
|
+
var subClassOfMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_SUB_CLASS_OF, {
|
|
177
201
|
transitive: true,
|
|
178
202
|
inference: "subsumption",
|
|
179
203
|
description: "Type inheritance (Podcast subClassOf Media)"
|
|
@@ -185,9 +209,9 @@ function subClassOf(child, parent) {
|
|
|
185
209
|
to: parent
|
|
186
210
|
};
|
|
187
211
|
}
|
|
188
|
-
var broaderMetaEdge = createMetaEdge(
|
|
212
|
+
var broaderMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_BROADER, {
|
|
189
213
|
transitive: true,
|
|
190
|
-
inverse:
|
|
214
|
+
inverse: chunkHRNQ3DVJ_cjs.META_EDGE_NARROWER,
|
|
191
215
|
inference: "hierarchy",
|
|
192
216
|
description: "Broader concept (ML broader AI)"
|
|
193
217
|
});
|
|
@@ -198,9 +222,9 @@ function broader(narrowerConcept, broaderConcept) {
|
|
|
198
222
|
to: broaderConcept
|
|
199
223
|
};
|
|
200
224
|
}
|
|
201
|
-
var narrowerMetaEdge = createMetaEdge(
|
|
225
|
+
var narrowerMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_NARROWER, {
|
|
202
226
|
transitive: true,
|
|
203
|
-
inverse:
|
|
227
|
+
inverse: chunkHRNQ3DVJ_cjs.META_EDGE_BROADER,
|
|
204
228
|
inference: "hierarchy",
|
|
205
229
|
description: "Narrower concept (AI narrower ML)"
|
|
206
230
|
});
|
|
@@ -211,7 +235,7 @@ function narrower(broaderConcept, narrowerConcept) {
|
|
|
211
235
|
to: narrowerConcept
|
|
212
236
|
};
|
|
213
237
|
}
|
|
214
|
-
var relatedToMetaEdge = createMetaEdge(
|
|
238
|
+
var relatedToMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_RELATED_TO, {
|
|
215
239
|
symmetric: true,
|
|
216
240
|
inference: "association",
|
|
217
241
|
description: "Non-hierarchical association"
|
|
@@ -223,7 +247,7 @@ function relatedTo(conceptA, conceptB) {
|
|
|
223
247
|
to: conceptB
|
|
224
248
|
};
|
|
225
249
|
}
|
|
226
|
-
var equivalentToMetaEdge = createMetaEdge(
|
|
250
|
+
var equivalentToMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_EQUIVALENT_TO, {
|
|
227
251
|
symmetric: true,
|
|
228
252
|
transitive: true,
|
|
229
253
|
inference: "substitution",
|
|
@@ -236,7 +260,7 @@ function equivalentTo(kindA, kindBOrIri) {
|
|
|
236
260
|
to: kindBOrIri
|
|
237
261
|
};
|
|
238
262
|
}
|
|
239
|
-
var sameAsMetaEdge = createMetaEdge(
|
|
263
|
+
var sameAsMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_SAME_AS, {
|
|
240
264
|
symmetric: true,
|
|
241
265
|
transitive: true,
|
|
242
266
|
inference: "substitution",
|
|
@@ -249,7 +273,7 @@ function sameAs(kindA, kindBOrIri) {
|
|
|
249
273
|
to: kindBOrIri
|
|
250
274
|
};
|
|
251
275
|
}
|
|
252
|
-
var differentFromMetaEdge = createMetaEdge(
|
|
276
|
+
var differentFromMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_DIFFERENT_FROM, {
|
|
253
277
|
symmetric: true,
|
|
254
278
|
inference: "constraint",
|
|
255
279
|
description: "Explicitly different individuals"
|
|
@@ -261,7 +285,7 @@ function differentFrom(kindA, kindB) {
|
|
|
261
285
|
to: kindB
|
|
262
286
|
};
|
|
263
287
|
}
|
|
264
|
-
var disjointWithMetaEdge = createMetaEdge(
|
|
288
|
+
var disjointWithMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_DISJOINT_WITH, {
|
|
265
289
|
symmetric: true,
|
|
266
290
|
inference: "constraint",
|
|
267
291
|
description: "Mutually exclusive types"
|
|
@@ -273,9 +297,9 @@ function disjointWith(kindA, kindB) {
|
|
|
273
297
|
to: kindB
|
|
274
298
|
};
|
|
275
299
|
}
|
|
276
|
-
var partOfMetaEdge = createMetaEdge(
|
|
300
|
+
var partOfMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_PART_OF, {
|
|
277
301
|
transitive: true,
|
|
278
|
-
inverse:
|
|
302
|
+
inverse: chunkHRNQ3DVJ_cjs.META_EDGE_HAS_PART,
|
|
279
303
|
inference: "composition",
|
|
280
304
|
description: "X is part of Y"
|
|
281
305
|
});
|
|
@@ -286,9 +310,9 @@ function partOf(part, whole) {
|
|
|
286
310
|
to: whole
|
|
287
311
|
};
|
|
288
312
|
}
|
|
289
|
-
var hasPartMetaEdge = createMetaEdge(
|
|
313
|
+
var hasPartMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_HAS_PART, {
|
|
290
314
|
transitive: true,
|
|
291
|
-
inverse:
|
|
315
|
+
inverse: chunkHRNQ3DVJ_cjs.META_EDGE_PART_OF,
|
|
292
316
|
inference: "composition",
|
|
293
317
|
description: "Y has part X"
|
|
294
318
|
});
|
|
@@ -299,12 +323,12 @@ function hasPart(whole, part) {
|
|
|
299
323
|
to: part
|
|
300
324
|
};
|
|
301
325
|
}
|
|
302
|
-
var inverseOfMetaEdge = createMetaEdge(
|
|
326
|
+
var inverseOfMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_INVERSE_OF, {
|
|
303
327
|
symmetric: true,
|
|
304
328
|
inference: "none",
|
|
305
329
|
description: "Edge A is inverse of edge B"
|
|
306
330
|
});
|
|
307
|
-
var impliesMetaEdge = createMetaEdge(
|
|
331
|
+
var impliesMetaEdge = createMetaEdge(chunkHRNQ3DVJ_cjs.META_EDGE_IMPLIES, {
|
|
308
332
|
transitive: true,
|
|
309
333
|
inference: "none",
|
|
310
334
|
description: "Edge A implies edge B exists"
|
|
@@ -565,6 +589,41 @@ function stringField(field2) {
|
|
|
565
589
|
ilike: (pattern) => stringOp("ilike", field2, pattern)
|
|
566
590
|
};
|
|
567
591
|
}
|
|
592
|
+
var DEFAULT_FULLTEXT_MATCH_K = 50;
|
|
593
|
+
function createFulltextAccessor(alias, hasSearchableField) {
|
|
594
|
+
return {
|
|
595
|
+
matches: (query, k, options) => {
|
|
596
|
+
if (!hasSearchableField()) {
|
|
597
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
598
|
+
`Cannot call .$fulltext.matches() on alias "${alias}" \u2014 its node kind has no fields declared with searchable(). Add at least one: \`title: searchable({ language: "english" })\`.`
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
return fulltextMatch(
|
|
602
|
+
fieldRef(alias, ["$fulltext"]),
|
|
603
|
+
query,
|
|
604
|
+
k ?? DEFAULT_FULLTEXT_MATCH_K,
|
|
605
|
+
options
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
function fulltextMatch(field2, query, limit, options) {
|
|
611
|
+
if (!Number.isFinite(limit) || limit <= 0) {
|
|
612
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
613
|
+
`matches() limit must be a positive finite number, got ${String(limit)}`
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
const expr = {
|
|
617
|
+
__type: "fulltext_match",
|
|
618
|
+
field: field2,
|
|
619
|
+
query,
|
|
620
|
+
mode: options?.mode ?? "websearch",
|
|
621
|
+
limit,
|
|
622
|
+
...options?.language === void 0 ? {} : { language: options.language },
|
|
623
|
+
...options?.minScore === void 0 ? {} : { minScore: options.minScore }
|
|
624
|
+
};
|
|
625
|
+
return predicate(expr);
|
|
626
|
+
}
|
|
568
627
|
function numberField(field2) {
|
|
569
628
|
return {
|
|
570
629
|
...baseFieldBuilder(field2),
|
|
@@ -664,7 +723,7 @@ function buildFieldBuilderForTypeInfo(field2, typeInfo) {
|
|
|
664
723
|
}
|
|
665
724
|
}
|
|
666
725
|
function resolvePointerTypeInfo(typeInfo, pointer) {
|
|
667
|
-
return
|
|
726
|
+
return chunkUVZHTBZ5_cjs.resolveFieldTypeInfoAtJsonPointer(typeInfo, pointer);
|
|
668
727
|
}
|
|
669
728
|
function objectOp(op, field2, pointer, value, options) {
|
|
670
729
|
const expr = {
|
|
@@ -687,8 +746,8 @@ function objectField(field2, options) {
|
|
|
687
746
|
return {
|
|
688
747
|
...baseFieldBuilder(field2),
|
|
689
748
|
get: (key) => {
|
|
690
|
-
const pointer =
|
|
691
|
-
const nestedPointer =
|
|
749
|
+
const pointer = chunkUVZHTBZ5_cjs.jsonPointer([key]);
|
|
750
|
+
const nestedPointer = chunkUVZHTBZ5_cjs.joinJsonPointers(basePointer, pointer);
|
|
692
751
|
const resolved = resolvePointerTypeInfo(options?.typeInfo, pointer);
|
|
693
752
|
const nestedRef = fieldRef(field2.alias, field2.path, {
|
|
694
753
|
jsonPointer: nestedPointer,
|
|
@@ -702,17 +761,17 @@ function objectField(field2, options) {
|
|
|
702
761
|
return buildFieldBuilderForTypeInfo(nestedRef, resolved);
|
|
703
762
|
},
|
|
704
763
|
hasKey: (key) => {
|
|
705
|
-
const pointer =
|
|
764
|
+
const pointer = chunkUVZHTBZ5_cjs.jsonPointer([key]);
|
|
706
765
|
resolvePointerTypeInfo(options?.typeInfo, pointer);
|
|
707
766
|
return objectOp("hasKey", field2, pointer);
|
|
708
767
|
},
|
|
709
768
|
hasPath: (pointer) => {
|
|
710
|
-
const normalized =
|
|
769
|
+
const normalized = chunkUVZHTBZ5_cjs.normalizeJsonPointer(pointer);
|
|
711
770
|
resolvePointerTypeInfo(options?.typeInfo, normalized);
|
|
712
771
|
return objectOp("hasPath", field2, normalized);
|
|
713
772
|
},
|
|
714
773
|
pathEquals: (pointer, value) => {
|
|
715
|
-
const normalized =
|
|
774
|
+
const normalized = chunkUVZHTBZ5_cjs.normalizeJsonPointer(pointer);
|
|
716
775
|
const resolved = resolvePointerTypeInfo(options?.typeInfo, normalized);
|
|
717
776
|
if (resolved && (resolved.valueType === "array" || resolved.valueType === "object")) {
|
|
718
777
|
throw new Error("pathEquals is only supported for scalar JSON values");
|
|
@@ -721,7 +780,7 @@ function objectField(field2, options) {
|
|
|
721
780
|
return objectOp("pathEquals", field2, normalized, value, predicateOptions);
|
|
722
781
|
},
|
|
723
782
|
pathContains: (pointer, value) => {
|
|
724
|
-
const normalized =
|
|
783
|
+
const normalized = chunkUVZHTBZ5_cjs.normalizeJsonPointer(pointer);
|
|
725
784
|
const resolved = resolvePointerTypeInfo(options?.typeInfo, normalized);
|
|
726
785
|
if (resolved && resolved.valueType !== "array") {
|
|
727
786
|
throw new Error("pathContains is only supported for JSON array values");
|
|
@@ -736,7 +795,7 @@ function objectField(field2, options) {
|
|
|
736
795
|
);
|
|
737
796
|
},
|
|
738
797
|
pathIsNull: (pointer) => {
|
|
739
|
-
const normalized =
|
|
798
|
+
const normalized = chunkUVZHTBZ5_cjs.normalizeJsonPointer(pointer);
|
|
740
799
|
const resolved = resolvePointerTypeInfo(options?.typeInfo, normalized);
|
|
741
800
|
const predicateOptions = resolved?.valueType === void 0 ? void 0 : { valueType: resolved.valueType };
|
|
742
801
|
return objectOp(
|
|
@@ -748,7 +807,7 @@ function objectField(field2, options) {
|
|
|
748
807
|
);
|
|
749
808
|
},
|
|
750
809
|
pathIsNotNull: (pointer) => {
|
|
751
|
-
const normalized =
|
|
810
|
+
const normalized = chunkUVZHTBZ5_cjs.normalizeJsonPointer(pointer);
|
|
752
811
|
const resolved = resolvePointerTypeInfo(options?.typeInfo, normalized);
|
|
753
812
|
const predicateOptions = resolved?.valueType === void 0 ? void 0 : { valueType: resolved.valueType };
|
|
754
813
|
return objectOp(
|
|
@@ -760,8 +819,8 @@ function objectField(field2, options) {
|
|
|
760
819
|
);
|
|
761
820
|
},
|
|
762
821
|
field: (pointer) => {
|
|
763
|
-
const normalized =
|
|
764
|
-
const nestedPointer =
|
|
822
|
+
const normalized = chunkUVZHTBZ5_cjs.normalizeJsonPointer(pointer);
|
|
823
|
+
const nestedPointer = chunkUVZHTBZ5_cjs.joinJsonPointers(basePointer, normalized);
|
|
765
824
|
const resolved = resolvePointerTypeInfo(options?.typeInfo, normalized);
|
|
766
825
|
const nestedRef = fieldRef(field2.alias, field2.path, {
|
|
767
826
|
jsonPointer: nestedPointer,
|
|
@@ -891,7 +950,7 @@ function getFieldPointer(field2) {
|
|
|
891
950
|
return field2.jsonPointer;
|
|
892
951
|
}
|
|
893
952
|
if (field2.path.length > 1 && field2.path[0] === "props") {
|
|
894
|
-
return
|
|
953
|
+
return chunkUVZHTBZ5_cjs.jsonPointer(field2.path.slice(1));
|
|
895
954
|
}
|
|
896
955
|
return void 0;
|
|
897
956
|
}
|
|
@@ -1140,11 +1199,13 @@ function compilePredicateExpression(expr, ctx) {
|
|
|
1140
1199
|
case "in_subquery": {
|
|
1141
1200
|
return compileInSubquery(expr, ctx);
|
|
1142
1201
|
}
|
|
1143
|
-
case "vector_similarity":
|
|
1144
|
-
|
|
1202
|
+
case "vector_similarity":
|
|
1203
|
+
case "fulltext_match": {
|
|
1204
|
+
return STRUCTURAL_PREDICATE_NOOP;
|
|
1145
1205
|
}
|
|
1146
1206
|
}
|
|
1147
1207
|
}
|
|
1208
|
+
var STRUCTURAL_PREDICATE_NOOP = drizzleOrm.sql.raw("1=1");
|
|
1148
1209
|
function compileComparisonPredicate(expr, dialect, cteColumnPrefix) {
|
|
1149
1210
|
if (isParameterRef(expr.right)) {
|
|
1150
1211
|
const parameterValueType = normalizeValueType2(expr.right.valueType) ?? normalizeValueType2(expr.left.valueType);
|
|
@@ -1248,7 +1309,7 @@ function compileArrayPredicate(expr, dialect, cteColumnPrefix) {
|
|
|
1248
1309
|
}
|
|
1249
1310
|
function compileObjectPredicate(expr, dialect, cteColumnPrefix) {
|
|
1250
1311
|
const basePointer = getFieldPointer(expr.field);
|
|
1251
|
-
const pointer =
|
|
1312
|
+
const pointer = chunkUVZHTBZ5_cjs.joinJsonPointers(basePointer, expr.pointer);
|
|
1252
1313
|
const column = compileFieldColumn(expr.field, void 0, cteColumnPrefix);
|
|
1253
1314
|
switch (expr.op) {
|
|
1254
1315
|
case "hasKey":
|
|
@@ -1398,45 +1459,61 @@ function compileInSubquery(expr, ctx) {
|
|
|
1398
1459
|
const subSql = ctx.compileQuery(expr.subquery, expr.subquery.graphId);
|
|
1399
1460
|
return expr.negated ? drizzleOrm.sql`${fieldSql} NOT IN (${subSql})` : drizzleOrm.sql`${fieldSql} IN (${subSql})`;
|
|
1400
1461
|
}
|
|
1401
|
-
function
|
|
1402
|
-
return drizzleOrm.sql.raw("1=1");
|
|
1403
|
-
}
|
|
1404
|
-
function extractVectorSimilarityPredicates(predicates) {
|
|
1462
|
+
function extractStructuralPredicates(predicates, isMatch, rejectionMessage) {
|
|
1405
1463
|
const results = [];
|
|
1406
1464
|
function visit(expr, inDisallowedBranch) {
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
1411
|
-
"Vector similarity predicates cannot be nested under OR or NOT. Use top-level AND combinations instead."
|
|
1412
|
-
);
|
|
1413
|
-
}
|
|
1414
|
-
results.push(expr);
|
|
1415
|
-
break;
|
|
1465
|
+
if (isMatch(expr)) {
|
|
1466
|
+
if (inDisallowedBranch) {
|
|
1467
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(rejectionMessage);
|
|
1416
1468
|
}
|
|
1469
|
+
results.push(expr);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
switch (expr.__type) {
|
|
1417
1473
|
case "and": {
|
|
1418
|
-
for (const
|
|
1419
|
-
|
|
1420
|
-
}
|
|
1421
|
-
break;
|
|
1474
|
+
for (const child of expr.predicates) visit(child, inDisallowedBranch);
|
|
1475
|
+
return;
|
|
1422
1476
|
}
|
|
1423
1477
|
case "or": {
|
|
1424
|
-
for (const
|
|
1425
|
-
|
|
1426
|
-
}
|
|
1427
|
-
break;
|
|
1478
|
+
for (const child of expr.predicates) visit(child, true);
|
|
1479
|
+
return;
|
|
1428
1480
|
}
|
|
1429
1481
|
case "not": {
|
|
1430
1482
|
visit(expr.predicate, true);
|
|
1431
|
-
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
case "comparison":
|
|
1486
|
+
case "string_op":
|
|
1487
|
+
case "null_check":
|
|
1488
|
+
case "between":
|
|
1489
|
+
case "array_op":
|
|
1490
|
+
case "object_op":
|
|
1491
|
+
case "aggregate_comparison":
|
|
1492
|
+
case "exists":
|
|
1493
|
+
case "in_subquery":
|
|
1494
|
+
case "vector_similarity":
|
|
1495
|
+
case "fulltext_match": {
|
|
1496
|
+
return;
|
|
1432
1497
|
}
|
|
1433
1498
|
}
|
|
1434
1499
|
}
|
|
1435
|
-
for (const pred of predicates)
|
|
1436
|
-
visit(pred.expression, false);
|
|
1437
|
-
}
|
|
1500
|
+
for (const pred of predicates) visit(pred.expression, false);
|
|
1438
1501
|
return results;
|
|
1439
1502
|
}
|
|
1503
|
+
function extractVectorSimilarityPredicates(predicates) {
|
|
1504
|
+
return extractStructuralPredicates(
|
|
1505
|
+
predicates,
|
|
1506
|
+
(expr) => expr.__type === "vector_similarity",
|
|
1507
|
+
"Vector similarity predicates cannot be nested under OR or NOT. Use top-level AND combinations instead."
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
function extractFulltextMatchPredicates(predicates) {
|
|
1511
|
+
return extractStructuralPredicates(
|
|
1512
|
+
predicates,
|
|
1513
|
+
(expr) => expr.__type === "fulltext_match",
|
|
1514
|
+
"Fulltext match predicates cannot be nested under OR or NOT. Use top-level AND combinations instead."
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1440
1517
|
|
|
1441
1518
|
// src/query/compiler/predicate-utils.ts
|
|
1442
1519
|
var EMPTY_PREDICATES = [];
|
|
@@ -1495,6 +1572,10 @@ function getNodeKindsForAlias(ast, alias) {
|
|
|
1495
1572
|
}
|
|
1496
1573
|
throw new chunkO5PST6TB_cjs.CompilerInvariantError(`Unknown traversal source alias: ${alias}`);
|
|
1497
1574
|
}
|
|
1575
|
+
function getHybridTargetAlias(vectorPredicate, fulltextPredicate) {
|
|
1576
|
+
if (!vectorPredicate || !fulltextPredicate) return void 0;
|
|
1577
|
+
return vectorPredicate.field.alias === fulltextPredicate.field.alias ? vectorPredicate.field.alias : void 0;
|
|
1578
|
+
}
|
|
1498
1579
|
|
|
1499
1580
|
// src/query/compiler/emitter/plan-inspector.ts
|
|
1500
1581
|
function collectPlanOperations(node, ops) {
|
|
@@ -1502,6 +1583,7 @@ function collectPlanOperations(node, ops) {
|
|
|
1502
1583
|
switch (node.op) {
|
|
1503
1584
|
case "aggregate":
|
|
1504
1585
|
case "filter":
|
|
1586
|
+
case "fulltext_match":
|
|
1505
1587
|
case "join":
|
|
1506
1588
|
case "limit_offset":
|
|
1507
1589
|
case "project":
|
|
@@ -1530,6 +1612,7 @@ function findUnaryNodeInProjectChain(rootNode, op) {
|
|
|
1530
1612
|
switch (currentNode.op) {
|
|
1531
1613
|
case "aggregate":
|
|
1532
1614
|
case "filter":
|
|
1615
|
+
case "fulltext_match":
|
|
1533
1616
|
case "join":
|
|
1534
1617
|
case "limit_offset":
|
|
1535
1618
|
case "recursive_expand":
|
|
@@ -1565,6 +1648,7 @@ function inspectProjectPlan(logicalPlan) {
|
|
|
1565
1648
|
);
|
|
1566
1649
|
return {
|
|
1567
1650
|
hasAggregate: operations.has("aggregate"),
|
|
1651
|
+
hasFulltextMatch: operations.has("fulltext_match"),
|
|
1568
1652
|
hasLimitOffset: operations.has("limit_offset"),
|
|
1569
1653
|
hasRecursiveExpand: operations.has("recursive_expand"),
|
|
1570
1654
|
hasSetOperation: operations.has("set_op"),
|
|
@@ -1616,6 +1700,7 @@ function findTopLevelLimitOffsetNode(rootNode) {
|
|
|
1616
1700
|
switch (currentNode.op) {
|
|
1617
1701
|
case "aggregate":
|
|
1618
1702
|
case "filter":
|
|
1703
|
+
case "fulltext_match":
|
|
1619
1704
|
case "join":
|
|
1620
1705
|
case "project":
|
|
1621
1706
|
case "recursive_expand":
|
|
@@ -1640,6 +1725,7 @@ function findTopLevelSortNode(rootNode) {
|
|
|
1640
1725
|
switch (currentNode.op) {
|
|
1641
1726
|
case "aggregate":
|
|
1642
1727
|
case "filter":
|
|
1728
|
+
case "fulltext_match":
|
|
1643
1729
|
case "join":
|
|
1644
1730
|
case "limit_offset":
|
|
1645
1731
|
case "project":
|
|
@@ -1774,16 +1860,16 @@ function assertStandardEmitterClauseAlignment(logicalPlan, input) {
|
|
|
1774
1860
|
{ component: "standard-emitter" }
|
|
1775
1861
|
);
|
|
1776
1862
|
}
|
|
1777
|
-
const expectsOrderBy = planShape.hasSort || planShape.hasVectorKnn;
|
|
1863
|
+
const expectsOrderBy = planShape.hasSort || planShape.hasVectorKnn || planShape.hasFulltextMatch;
|
|
1778
1864
|
if (expectsOrderBy && input.orderBy === void 0) {
|
|
1779
1865
|
throw new chunkO5PST6TB_cjs.CompilerInvariantError(
|
|
1780
|
-
"Standard SQL emitter expected ORDER BY clause for plan containing a sort or
|
|
1866
|
+
"Standard SQL emitter expected ORDER BY clause for plan containing a sort, vector_knn, or fulltext_match node",
|
|
1781
1867
|
{ component: "standard-emitter" }
|
|
1782
1868
|
);
|
|
1783
1869
|
}
|
|
1784
1870
|
if (!expectsOrderBy && input.orderBy !== void 0) {
|
|
1785
1871
|
throw new chunkO5PST6TB_cjs.CompilerInvariantError(
|
|
1786
|
-
"Standard SQL emitter received ORDER BY clause for a plan without sort or
|
|
1872
|
+
"Standard SQL emitter received ORDER BY clause for a plan without sort, vector_knn, or fulltext_match nodes",
|
|
1787
1873
|
{ component: "standard-emitter" }
|
|
1788
1874
|
);
|
|
1789
1875
|
}
|
|
@@ -1822,6 +1908,62 @@ function emitStandardQuerySql(input) {
|
|
|
1822
1908
|
return drizzleOrm.sql.join(parts, drizzleOrm.sql` `);
|
|
1823
1909
|
}
|
|
1824
1910
|
|
|
1911
|
+
// src/query/ast.ts
|
|
1912
|
+
var DEFAULT_RRF_K = 60;
|
|
1913
|
+
var DEFAULT_RRF_WEIGHT = 1;
|
|
1914
|
+
function mergeEdgeKinds(traversal) {
|
|
1915
|
+
const inverse = traversal.inverseEdgeKinds;
|
|
1916
|
+
if (inverse === void 0 || inverse.length === 0) return traversal.edgeKinds;
|
|
1917
|
+
return [
|
|
1918
|
+
...traversal.edgeKinds,
|
|
1919
|
+
...inverse.filter((kind) => !traversal.edgeKinds.includes(kind))
|
|
1920
|
+
];
|
|
1921
|
+
}
|
|
1922
|
+
var DEFAULT_TABLE_NAMES = {
|
|
1923
|
+
nodes: "typegraph_nodes",
|
|
1924
|
+
edges: "typegraph_edges",
|
|
1925
|
+
embeddings: "typegraph_node_embeddings",
|
|
1926
|
+
fulltext: "typegraph_node_fulltext"
|
|
1927
|
+
};
|
|
1928
|
+
var VALID_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_$]*$/i;
|
|
1929
|
+
function validateTableName(name, label) {
|
|
1930
|
+
if (!name || name.length === 0) {
|
|
1931
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(`${label} table name cannot be empty`);
|
|
1932
|
+
}
|
|
1933
|
+
if (name.length > chunk3JK66E3I_cjs.MAX_PG_IDENTIFIER_LENGTH) {
|
|
1934
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
1935
|
+
`${label} table name exceeds maximum length of ${chunk3JK66E3I_cjs.MAX_PG_IDENTIFIER_LENGTH} characters`
|
|
1936
|
+
);
|
|
1937
|
+
}
|
|
1938
|
+
if (!VALID_IDENTIFIER_PATTERN.test(name)) {
|
|
1939
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
1940
|
+
`${label} table name "${name}" is not a valid SQL identifier. Table names must start with a letter or underscore and contain only letters, digits, underscores, or dollar signs.`
|
|
1941
|
+
);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
function quoteIdentifier(name) {
|
|
1945
|
+
return `"${name.replaceAll('"', '""')}"`;
|
|
1946
|
+
}
|
|
1947
|
+
function createSqlSchema(names = {}) {
|
|
1948
|
+
const tables = { ...DEFAULT_TABLE_NAMES, ...names };
|
|
1949
|
+
validateTableName(tables.nodes, "nodes");
|
|
1950
|
+
validateTableName(tables.edges, "edges");
|
|
1951
|
+
validateTableName(tables.embeddings, "embeddings");
|
|
1952
|
+
validateTableName(tables.fulltext, "fulltext");
|
|
1953
|
+
return {
|
|
1954
|
+
tables,
|
|
1955
|
+
nodesTable: drizzleOrm.sql.raw(quoteIdentifier(tables.nodes)),
|
|
1956
|
+
edgesTable: drizzleOrm.sql.raw(quoteIdentifier(tables.edges)),
|
|
1957
|
+
embeddingsTable: drizzleOrm.sql.raw(quoteIdentifier(tables.embeddings)),
|
|
1958
|
+
fulltextTable: drizzleOrm.sql.raw(quoteIdentifier(tables.fulltext))
|
|
1959
|
+
};
|
|
1960
|
+
}
|
|
1961
|
+
var DEFAULT_SQL_SCHEMA = createSqlSchema();
|
|
1962
|
+
var ALIAS_CTE_PREFIX = "cte_";
|
|
1963
|
+
var EMBEDDINGS_CTE_ALIAS = "cte_embeddings";
|
|
1964
|
+
var FULLTEXT_CTE_ALIAS = "cte_fulltext";
|
|
1965
|
+
var HYBRID_CANDIDATES_CTE_ALIAS = "cte_relevance_candidates";
|
|
1966
|
+
|
|
1825
1967
|
// src/query/compiler/typed-json-extract.ts
|
|
1826
1968
|
function compileTypedJsonExtract(input) {
|
|
1827
1969
|
const { column, dialect, pointer, valueType } = input;
|
|
@@ -1875,7 +2017,7 @@ var EDGE_COLUMNS = [
|
|
|
1875
2017
|
"deleted_at"
|
|
1876
2018
|
];
|
|
1877
2019
|
var EMPTY_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
1878
|
-
function
|
|
2020
|
+
function quoteIdentifier2(identifier) {
|
|
1879
2021
|
return drizzleOrm.sql.raw(`"${identifier.replaceAll('"', '""')}"`);
|
|
1880
2022
|
}
|
|
1881
2023
|
function shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns) {
|
|
@@ -1929,6 +2071,21 @@ function compileColumnReference(tableAlias, column) {
|
|
|
1929
2071
|
}
|
|
1930
2072
|
return drizzleOrm.sql`${drizzleOrm.sql.raw(tableAlias)}.${drizzleOrm.sql.raw(column)}`;
|
|
1931
2073
|
}
|
|
2074
|
+
function qualifyColumn(owner, name) {
|
|
2075
|
+
return drizzleOrm.sql`${quoteIdentifier2(owner)}.${quoteIdentifier2(name)}`;
|
|
2076
|
+
}
|
|
2077
|
+
var SCOPED_RELEVANCE_NODES_ALIAS = "scoped_relevance_nodes";
|
|
2078
|
+
function buildScopedNodeIdsSubquery(nodeAlias) {
|
|
2079
|
+
const cteAlias = `${ALIAS_CTE_PREFIX}${nodeAlias}`;
|
|
2080
|
+
return drizzleOrm.sql`
|
|
2081
|
+
(
|
|
2082
|
+
SELECT DISTINCT
|
|
2083
|
+
${qualifyColumn(cteAlias, `${nodeAlias}_id`)} AS node_id,
|
|
2084
|
+
${qualifyColumn(cteAlias, `${nodeAlias}_kind`)} AS node_kind
|
|
2085
|
+
FROM ${quoteIdentifier2(cteAlias)}
|
|
2086
|
+
) AS ${drizzleOrm.sql.raw(SCOPED_RELEVANCE_NODES_ALIAS)}
|
|
2087
|
+
`;
|
|
2088
|
+
}
|
|
1932
2089
|
function compileNodeSelectColumns(tableAlias, alias, requiredColumns) {
|
|
1933
2090
|
return NODE_COLUMNS.filter(
|
|
1934
2091
|
(column) => column === "id" || column === "kind" || shouldProjectColumn(requiredColumns, column)
|
|
@@ -1947,6 +2104,7 @@ function buildStandardStartCte(input) {
|
|
|
1947
2104
|
const { ast, ctx, graphId, predicateIndex, requiredColumnsByAlias } = input;
|
|
1948
2105
|
const alias = ast.start.alias;
|
|
1949
2106
|
const kinds = ast.start.kinds;
|
|
2107
|
+
const cteMaterialization = ctx.dialect.capabilities.emitNotMaterializedHint ? drizzleOrm.sql`NOT MATERIALIZED ` : drizzleOrm.sql``;
|
|
1950
2108
|
const kindFilter = compileKindFilter(drizzleOrm.sql.raw("kind"), kinds);
|
|
1951
2109
|
const temporalFilter = input.temporalFilterPass.forAlias();
|
|
1952
2110
|
const cteContext = { ...ctx, cteColumnPrefix: "" };
|
|
@@ -1961,14 +2119,19 @@ function buildStandardStartCte(input) {
|
|
|
1961
2119
|
...predicateClauses
|
|
1962
2120
|
];
|
|
1963
2121
|
const effectiveRequiredColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(alias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
2122
|
+
const limitClause = input.limitOffset === void 0 ? drizzleOrm.sql`` : input.limitOffset.offset === void 0 ? drizzleOrm.sql`
|
|
2123
|
+
LIMIT ${input.limitOffset.limit}
|
|
2124
|
+
` : drizzleOrm.sql`
|
|
2125
|
+
LIMIT ${input.limitOffset.limit} OFFSET ${input.limitOffset.offset}
|
|
2126
|
+
`;
|
|
1964
2127
|
return drizzleOrm.sql`
|
|
1965
|
-
cte_${drizzleOrm.sql.raw(alias)} AS (
|
|
2128
|
+
cte_${drizzleOrm.sql.raw(alias)} AS ${cteMaterialization}(
|
|
1966
2129
|
SELECT ${drizzleOrm.sql.join(
|
|
1967
2130
|
compileNodeSelectColumns(void 0, alias, effectiveRequiredColumns),
|
|
1968
2131
|
drizzleOrm.sql`, `
|
|
1969
2132
|
)}
|
|
1970
2133
|
FROM ${ctx.schema.nodesTable}
|
|
1971
|
-
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
|
|
2134
|
+
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}${limitClause}
|
|
1972
2135
|
)
|
|
1973
2136
|
`;
|
|
1974
2137
|
}
|
|
@@ -2032,7 +2195,7 @@ function buildStandardTraversalCte(input) {
|
|
|
2032
2195
|
...compileEdgeSelectColumns("e", edgeAlias, requiredEdgeColumns),
|
|
2033
2196
|
...compileNodeSelectColumns("n", nodeAlias, requiredNodeColumns)
|
|
2034
2197
|
];
|
|
2035
|
-
const cteMaterialization = materializeCte ? drizzleOrm.sql`MATERIALIZED ` : drizzleOrm.sql``;
|
|
2198
|
+
const cteMaterialization = materializeCte ? drizzleOrm.sql`MATERIALIZED ` : ctx.dialect.capabilities.emitNotMaterializedHint ? drizzleOrm.sql`NOT MATERIALIZED ` : drizzleOrm.sql``;
|
|
2036
2199
|
function compileTraversalBranch(branch) {
|
|
2037
2200
|
const whereClauses = [
|
|
2038
2201
|
...baseWhereClauses,
|
|
@@ -2181,7 +2344,7 @@ function buildStandardProjection(input) {
|
|
|
2181
2344
|
}
|
|
2182
2345
|
const projectedFields = fields.map((field2) => {
|
|
2183
2346
|
const source = compileProjectedSource(field2, dialect);
|
|
2184
|
-
return drizzleOrm.sql`${source} AS ${
|
|
2347
|
+
return drizzleOrm.sql`${source} AS ${quoteIdentifier2(field2.outputName)}`;
|
|
2185
2348
|
});
|
|
2186
2349
|
return drizzleOrm.sql.join(projectedFields, drizzleOrm.sql`, `);
|
|
2187
2350
|
}
|
|
@@ -2201,23 +2364,67 @@ function compileSelectiveProjection(fields, dialect, ast, collapsedTraversalCteA
|
|
|
2201
2364
|
const cteAlias = collapsedTraversalCteAlias ?? aliasToCte.get(field2.alias) ?? `cte_${field2.alias}`;
|
|
2202
2365
|
if (field2.isSystemField) {
|
|
2203
2366
|
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
2204
|
-
return drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${
|
|
2367
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier2(field2.outputName)}`;
|
|
2205
2368
|
}
|
|
2206
2369
|
const propsColumn = `${field2.alias}_props`;
|
|
2207
2370
|
const column = drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(propsColumn)}`;
|
|
2208
|
-
const pointer =
|
|
2371
|
+
const pointer = chunkUVZHTBZ5_cjs.jsonPointer([field2.field]);
|
|
2209
2372
|
const extracted = compileTypedJsonExtract({
|
|
2210
2373
|
column,
|
|
2211
2374
|
dialect,
|
|
2212
2375
|
pointer,
|
|
2213
2376
|
valueType: field2.valueType
|
|
2214
2377
|
});
|
|
2215
|
-
return drizzleOrm.sql`${extracted} AS ${
|
|
2378
|
+
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier2(field2.outputName)}`;
|
|
2216
2379
|
});
|
|
2217
2380
|
return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
|
|
2218
2381
|
}
|
|
2382
|
+
function buildRelevanceJoins(vectorPredicate, fulltextPredicate) {
|
|
2383
|
+
const hybridTargetAlias = getHybridTargetAlias(
|
|
2384
|
+
vectorPredicate,
|
|
2385
|
+
fulltextPredicate
|
|
2386
|
+
);
|
|
2387
|
+
if (hybridTargetAlias !== void 0) {
|
|
2388
|
+
return [
|
|
2389
|
+
buildHybridCandidateJoin(hybridTargetAlias),
|
|
2390
|
+
buildRelevanceJoin(EMBEDDINGS_CTE_ALIAS, hybridTargetAlias, "LEFT JOIN"),
|
|
2391
|
+
buildRelevanceJoin(FULLTEXT_CTE_ALIAS, hybridTargetAlias, "LEFT JOIN")
|
|
2392
|
+
];
|
|
2393
|
+
}
|
|
2394
|
+
const joins = [];
|
|
2395
|
+
if (vectorPredicate) {
|
|
2396
|
+
joins.push(
|
|
2397
|
+
buildRelevanceJoin(EMBEDDINGS_CTE_ALIAS, vectorPredicate.field.alias)
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
if (fulltextPredicate) {
|
|
2401
|
+
joins.push(
|
|
2402
|
+
buildRelevanceJoin(FULLTEXT_CTE_ALIAS, fulltextPredicate.field.alias)
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2405
|
+
return joins;
|
|
2406
|
+
}
|
|
2407
|
+
function buildHybridCandidateJoin(nodeAlias) {
|
|
2408
|
+
const candidateCte = drizzleOrm.sql.raw(HYBRID_CANDIDATES_CTE_ALIAS);
|
|
2409
|
+
const node = drizzleOrm.sql.raw(`${ALIAS_CTE_PREFIX}${nodeAlias}`);
|
|
2410
|
+
const idColumn = drizzleOrm.sql.raw(`${nodeAlias}_id`);
|
|
2411
|
+
const kindColumn = drizzleOrm.sql.raw(`${nodeAlias}_kind`);
|
|
2412
|
+
return drizzleOrm.sql`INNER JOIN ${candidateCte} ON ${candidateCte}.node_id = ${node}.${idColumn} AND ${candidateCte}.node_kind = ${node}.${kindColumn}`;
|
|
2413
|
+
}
|
|
2414
|
+
function buildRelevanceJoin(cteAlias, nodeAlias, joinType = "INNER JOIN") {
|
|
2415
|
+
const cte = drizzleOrm.sql.raw(cteAlias);
|
|
2416
|
+
const node = drizzleOrm.sql.raw(`${ALIAS_CTE_PREFIX}${nodeAlias}`);
|
|
2417
|
+
const idColumn = drizzleOrm.sql.raw(`${nodeAlias}_id`);
|
|
2418
|
+
const kindColumn = drizzleOrm.sql.raw(`${nodeAlias}_kind`);
|
|
2419
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(joinType)} ${cte} ON ${cte}.node_id = ${node}.${idColumn} AND ${cte}.node_kind = ${node}.${kindColumn}`;
|
|
2420
|
+
}
|
|
2219
2421
|
function buildStandardFromClause(input) {
|
|
2220
|
-
const {
|
|
2422
|
+
const {
|
|
2423
|
+
ast,
|
|
2424
|
+
collapsedTraversalCteAlias,
|
|
2425
|
+
fulltextPredicate,
|
|
2426
|
+
vectorPredicate
|
|
2427
|
+
} = input;
|
|
2221
2428
|
if (collapsedTraversalCteAlias !== void 0) {
|
|
2222
2429
|
return drizzleOrm.sql`FROM ${drizzleOrm.sql.raw(collapsedTraversalCteAlias)}`;
|
|
2223
2430
|
}
|
|
@@ -2232,11 +2439,8 @@ function buildStandardFromClause(input) {
|
|
|
2232
2439
|
drizzleOrm.sql`${drizzleOrm.sql.raw(joinType)} ${drizzleOrm.sql.raw(cteAlias)} ON ${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id = cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id AND ${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind = cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind`
|
|
2233
2440
|
);
|
|
2234
2441
|
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
joins.push(
|
|
2238
|
-
drizzleOrm.sql`INNER JOIN cte_embeddings ON cte_embeddings.node_id = cte_${drizzleOrm.sql.raw(nodeAlias)}.${drizzleOrm.sql.raw(nodeAlias)}_id`
|
|
2239
|
-
);
|
|
2442
|
+
for (const join of buildRelevanceJoins(vectorPredicate, fulltextPredicate)) {
|
|
2443
|
+
joins.push(join);
|
|
2240
2444
|
}
|
|
2241
2445
|
return joins.length === 0 ? fromClause : drizzleOrm.sql`${fromClause} ${drizzleOrm.sql.join(joins, drizzleOrm.sql` `)}`;
|
|
2242
2446
|
}
|
|
@@ -2275,6 +2479,15 @@ function fieldRefKey(field2) {
|
|
|
2275
2479
|
const pointer = field2.jsonPointer ?? "";
|
|
2276
2480
|
return `${field2.alias}:${field2.path.join(".")}:${pointer}`;
|
|
2277
2481
|
}
|
|
2482
|
+
function resolveEmbeddingFieldPath(field2) {
|
|
2483
|
+
if (field2.jsonPointer !== void 0 && field2.jsonPointer !== "" && field2.jsonPointer !== "/") {
|
|
2484
|
+
return field2.jsonPointer.replace(/^\//u, "").replaceAll("/", ".");
|
|
2485
|
+
}
|
|
2486
|
+
if (field2.path[0] === "props") {
|
|
2487
|
+
return field2.path.slice(1).join(".");
|
|
2488
|
+
}
|
|
2489
|
+
return field2.path.join(".");
|
|
2490
|
+
}
|
|
2278
2491
|
function buildStandardGroupBy(input) {
|
|
2279
2492
|
const { ast, dialect } = input;
|
|
2280
2493
|
if (!ast.groupBy || ast.groupBy.fields.length === 0) {
|
|
@@ -2321,18 +2534,29 @@ function buildStandardHaving(input) {
|
|
|
2321
2534
|
return drizzleOrm.sql`HAVING ${condition}`;
|
|
2322
2535
|
}
|
|
2323
2536
|
function buildStandardEmbeddingsCte(input) {
|
|
2324
|
-
const { ctx, graphId, vectorPredicate } = input;
|
|
2537
|
+
const { ctx, graphId, nodeKinds, vectorPredicate } = input;
|
|
2325
2538
|
const { dialect } = ctx;
|
|
2326
2539
|
const { field: field2, metric, minScore, queryEmbedding } = vectorPredicate;
|
|
2327
|
-
const
|
|
2540
|
+
const embeddingsTableName = ctx.schema.tables.embeddings;
|
|
2541
|
+
if (nodeKinds.length === 0) {
|
|
2542
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2543
|
+
"Vector predicate must resolve to at least one node kind"
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
const fieldPath = resolveEmbeddingFieldPath(field2);
|
|
2328
2547
|
const distanceExpr = dialect.vectorDistance(
|
|
2329
|
-
|
|
2548
|
+
qualifyColumn(embeddingsTableName, "embedding"),
|
|
2330
2549
|
queryEmbedding,
|
|
2331
2550
|
metric
|
|
2332
2551
|
);
|
|
2552
|
+
const scopedNodes = buildScopedNodeIdsSubquery(field2.alias);
|
|
2333
2553
|
const conditions = [
|
|
2334
|
-
drizzleOrm.sql
|
|
2335
|
-
|
|
2554
|
+
drizzleOrm.sql`${qualifyColumn(embeddingsTableName, "graph_id")} = ${graphId}`,
|
|
2555
|
+
compileKindFilter(
|
|
2556
|
+
qualifyColumn(embeddingsTableName, "node_kind"),
|
|
2557
|
+
nodeKinds
|
|
2558
|
+
),
|
|
2559
|
+
drizzleOrm.sql`${qualifyColumn(embeddingsTableName, "field_path")} = ${fieldPath}`
|
|
2336
2560
|
];
|
|
2337
2561
|
if (minScore !== void 0) {
|
|
2338
2562
|
conditions.push(
|
|
@@ -2341,14 +2565,29 @@ function buildStandardEmbeddingsCte(input) {
|
|
|
2341
2565
|
}
|
|
2342
2566
|
const scoreExpr = compileVectorScoreExpression(distanceExpr, metric);
|
|
2343
2567
|
return drizzleOrm.sql`
|
|
2344
|
-
|
|
2568
|
+
${drizzleOrm.sql.raw(EMBEDDINGS_CTE_ALIAS)} AS (
|
|
2345
2569
|
SELECT
|
|
2346
2570
|
node_id,
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2571
|
+
node_kind,
|
|
2572
|
+
distance,
|
|
2573
|
+
score,
|
|
2574
|
+
ROW_NUMBER() OVER (ORDER BY distance ASC) AS ord
|
|
2575
|
+
FROM (
|
|
2576
|
+
SELECT
|
|
2577
|
+
${qualifyColumn(embeddingsTableName, "node_id")} AS node_id,
|
|
2578
|
+
${qualifyColumn(embeddingsTableName, "node_kind")} AS node_kind,
|
|
2579
|
+
${distanceExpr} AS distance,
|
|
2580
|
+
${scoreExpr} AS score
|
|
2581
|
+
FROM ${ctx.schema.embeddingsTable}
|
|
2582
|
+
INNER JOIN ${scopedNodes}
|
|
2583
|
+
ON ${drizzleOrm.sql.raw(`${SCOPED_RELEVANCE_NODES_ALIAS}.node_id`)} =
|
|
2584
|
+
${qualifyColumn(embeddingsTableName, "node_id")}
|
|
2585
|
+
AND ${drizzleOrm.sql.raw(`${SCOPED_RELEVANCE_NODES_ALIAS}.node_kind`)} =
|
|
2586
|
+
${qualifyColumn(embeddingsTableName, "node_kind")}
|
|
2587
|
+
WHERE ${drizzleOrm.sql.join(conditions, drizzleOrm.sql` AND `)}
|
|
2588
|
+
ORDER BY distance ASC
|
|
2589
|
+
LIMIT ${vectorPredicate.limit}
|
|
2590
|
+
) AS vec_inner
|
|
2352
2591
|
)
|
|
2353
2592
|
`;
|
|
2354
2593
|
}
|
|
@@ -2378,37 +2617,130 @@ function compileVectorMinScoreCondition(distanceExpr, metric, minScore) {
|
|
|
2378
2617
|
}
|
|
2379
2618
|
}
|
|
2380
2619
|
}
|
|
2381
|
-
function
|
|
2382
|
-
const {
|
|
2383
|
-
const
|
|
2384
|
-
const
|
|
2385
|
-
if (
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2620
|
+
function buildStandardFulltextCte(input) {
|
|
2621
|
+
const { ctx, fulltextPredicate, graphId, nodeKinds } = input;
|
|
2622
|
+
const { dialect, schema } = ctx;
|
|
2623
|
+
const { query, mode, language, limit, minScore } = fulltextPredicate;
|
|
2624
|
+
if (nodeKinds.length === 0) {
|
|
2625
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2626
|
+
"Fulltext predicate must resolve to at least one node kind"
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2629
|
+
const tableName = schema.tables.fulltext;
|
|
2630
|
+
const scopedNodes = buildScopedNodeIdsSubquery(fulltextPredicate.field.alias);
|
|
2631
|
+
const fulltextStrategy = dialect.fulltext;
|
|
2632
|
+
if (fulltextStrategy === void 0) {
|
|
2633
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2634
|
+
`Fulltext match predicates are not supported for dialect "${dialect.name}"`
|
|
2635
|
+
);
|
|
2636
|
+
}
|
|
2637
|
+
const matchCondition = fulltextStrategy.matchCondition(
|
|
2638
|
+
tableName,
|
|
2639
|
+
query,
|
|
2640
|
+
mode,
|
|
2641
|
+
language
|
|
2642
|
+
);
|
|
2643
|
+
const rankExpression = fulltextStrategy.rankExpression(
|
|
2644
|
+
tableName,
|
|
2645
|
+
query,
|
|
2646
|
+
mode,
|
|
2647
|
+
language
|
|
2648
|
+
);
|
|
2649
|
+
const conditions = [
|
|
2650
|
+
drizzleOrm.sql`${qualifyColumn(tableName, "graph_id")} = ${graphId}`,
|
|
2651
|
+
compileKindFilter(qualifyColumn(tableName, "node_kind"), nodeKinds),
|
|
2652
|
+
matchCondition
|
|
2653
|
+
];
|
|
2654
|
+
if (minScore !== void 0) {
|
|
2655
|
+
conditions.push(drizzleOrm.sql`${rankExpression} >= ${minScore}`);
|
|
2656
|
+
}
|
|
2657
|
+
return drizzleOrm.sql`
|
|
2658
|
+
${drizzleOrm.sql.raw(FULLTEXT_CTE_ALIAS)} AS (
|
|
2659
|
+
SELECT
|
|
2660
|
+
node_id,
|
|
2661
|
+
node_kind,
|
|
2662
|
+
rank,
|
|
2663
|
+
ROW_NUMBER() OVER (ORDER BY rank DESC, node_id ASC) AS ord
|
|
2664
|
+
FROM (
|
|
2665
|
+
SELECT
|
|
2666
|
+
${qualifyColumn(tableName, "node_id")} AS node_id,
|
|
2667
|
+
${qualifyColumn(tableName, "node_kind")} AS node_kind,
|
|
2668
|
+
${rankExpression} AS rank
|
|
2669
|
+
FROM ${schema.fulltextTable}
|
|
2670
|
+
INNER JOIN ${scopedNodes}
|
|
2671
|
+
ON ${drizzleOrm.sql.raw(`${SCOPED_RELEVANCE_NODES_ALIAS}.node_id`)} =
|
|
2672
|
+
${qualifyColumn(tableName, "node_id")}
|
|
2673
|
+
AND ${drizzleOrm.sql.raw(`${SCOPED_RELEVANCE_NODES_ALIAS}.node_kind`)} =
|
|
2674
|
+
${qualifyColumn(tableName, "node_kind")}
|
|
2675
|
+
WHERE ${drizzleOrm.sql.join(conditions, drizzleOrm.sql` AND `)}
|
|
2676
|
+
ORDER BY rank DESC, ${qualifyColumn(tableName, "node_id")} ASC
|
|
2677
|
+
LIMIT ${limit}
|
|
2678
|
+
) AS fts_inner
|
|
2679
|
+
)
|
|
2680
|
+
`;
|
|
2681
|
+
}
|
|
2682
|
+
function buildStandardHybridCandidateCte() {
|
|
2683
|
+
return drizzleOrm.sql`
|
|
2684
|
+
${drizzleOrm.sql.raw(HYBRID_CANDIDATES_CTE_ALIAS)} AS (
|
|
2685
|
+
SELECT node_id, node_kind FROM ${drizzleOrm.sql.raw(EMBEDDINGS_CTE_ALIAS)}
|
|
2686
|
+
UNION
|
|
2687
|
+
SELECT node_id, node_kind FROM ${drizzleOrm.sql.raw(FULLTEXT_CTE_ALIAS)}
|
|
2688
|
+
)
|
|
2689
|
+
`;
|
|
2690
|
+
}
|
|
2691
|
+
function compileUserOrderBy(ast, dialect) {
|
|
2692
|
+
if (!ast.orderBy || ast.orderBy.length === 0) return [];
|
|
2693
|
+
const aliasToCte = buildAliasToCteMap(ast);
|
|
2694
|
+
const fragments = [];
|
|
2695
|
+
for (const orderSpec of ast.orderBy) {
|
|
2696
|
+
const valueType = orderSpec.field.valueType;
|
|
2697
|
+
if (valueType === "array" || valueType === "object") {
|
|
2698
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2699
|
+
"Ordering by JSON arrays or objects is not supported"
|
|
2407
2700
|
);
|
|
2408
2701
|
}
|
|
2702
|
+
const cteAlias = aliasToCte.get(orderSpec.field.alias) ?? `${ALIAS_CTE_PREFIX}${orderSpec.field.alias}`;
|
|
2703
|
+
const field2 = compileFieldValue(
|
|
2704
|
+
orderSpec.field,
|
|
2705
|
+
dialect,
|
|
2706
|
+
valueType,
|
|
2707
|
+
cteAlias
|
|
2708
|
+
);
|
|
2709
|
+
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
2710
|
+
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
2711
|
+
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
2712
|
+
fragments.push(
|
|
2713
|
+
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
2714
|
+
drizzleOrm.sql`${field2} ${direction}`
|
|
2715
|
+
);
|
|
2409
2716
|
}
|
|
2410
|
-
|
|
2411
|
-
|
|
2717
|
+
return fragments;
|
|
2718
|
+
}
|
|
2719
|
+
function buildStandardFulltextOrderBy(input) {
|
|
2720
|
+
const { ast, dialect } = input;
|
|
2721
|
+
const rankOrder = drizzleOrm.sql.raw(`${FULLTEXT_CTE_ALIAS}.rank DESC`);
|
|
2722
|
+
const userOrders = compileUserOrderBy(ast, dialect);
|
|
2723
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join([rankOrder, ...userOrders], drizzleOrm.sql`, `)}`;
|
|
2724
|
+
}
|
|
2725
|
+
function buildStandardHybridRrfOrderBy(input) {
|
|
2726
|
+
const { ast, dialect, fusion } = input;
|
|
2727
|
+
const k = fusion?.k ?? DEFAULT_RRF_K;
|
|
2728
|
+
const vectorWeight = fusion?.weights?.vector ?? DEFAULT_RRF_WEIGHT;
|
|
2729
|
+
const fulltextWeight = fusion?.weights?.fulltext ?? DEFAULT_RRF_WEIGHT;
|
|
2730
|
+
const rrfOrder = drizzleOrm.sql.raw(
|
|
2731
|
+
`(COALESCE(${vectorWeight} / (${k} + ${EMBEDDINGS_CTE_ALIAS}.ord), 0) + COALESCE(${fulltextWeight} / (${k} + ${FULLTEXT_CTE_ALIAS}.ord), 0)) DESC`
|
|
2732
|
+
);
|
|
2733
|
+
const idTiebreak = drizzleOrm.sql.raw(
|
|
2734
|
+
`COALESCE(${FULLTEXT_CTE_ALIAS}.node_id, ${EMBEDDINGS_CTE_ALIAS}.node_id) ASC`
|
|
2735
|
+
);
|
|
2736
|
+
const userOrders = compileUserOrderBy(ast, dialect);
|
|
2737
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join([rrfOrder, ...userOrders, idTiebreak], drizzleOrm.sql`, `)}`;
|
|
2738
|
+
}
|
|
2739
|
+
function buildStandardVectorOrderBy(input) {
|
|
2740
|
+
const { ast, dialect } = input;
|
|
2741
|
+
const distanceOrder = drizzleOrm.sql.raw(`${EMBEDDINGS_CTE_ALIAS}.distance ASC`);
|
|
2742
|
+
const userOrders = compileUserOrderBy(ast, dialect);
|
|
2743
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join([distanceOrder, ...userOrders], drizzleOrm.sql`, `)}`;
|
|
2412
2744
|
}
|
|
2413
2745
|
function buildLimitOffsetClause(input) {
|
|
2414
2746
|
const { limit, offset } = input;
|
|
@@ -2422,6 +2754,74 @@ function buildLimitOffsetClause(input) {
|
|
|
2422
2754
|
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
2423
2755
|
}
|
|
2424
2756
|
|
|
2757
|
+
// src/query/compiler/passes/fulltext.ts
|
|
2758
|
+
function runFulltextPredicatePass(ast, dialect) {
|
|
2759
|
+
const fulltextPredicates = extractFulltextMatchPredicates(ast.predicates);
|
|
2760
|
+
if (fulltextPredicates.length > 1) {
|
|
2761
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2762
|
+
"Multiple fulltext match predicates in a single query are not supported"
|
|
2763
|
+
);
|
|
2764
|
+
}
|
|
2765
|
+
const fulltextPredicate = fulltextPredicates[0];
|
|
2766
|
+
if (fulltextPredicate === void 0) {
|
|
2767
|
+
return { fulltextPredicate: void 0 };
|
|
2768
|
+
}
|
|
2769
|
+
if (!dialect.capabilities.supportsFulltext) {
|
|
2770
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2771
|
+
`Fulltext match predicates are not supported for dialect "${dialect.name}"`
|
|
2772
|
+
);
|
|
2773
|
+
}
|
|
2774
|
+
const strategy = dialect.fulltext;
|
|
2775
|
+
if (strategy === void 0) {
|
|
2776
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2777
|
+
`Dialect "${dialect.name}" advertises fulltext support but has no strategy configured`
|
|
2778
|
+
);
|
|
2779
|
+
}
|
|
2780
|
+
if (!strategy.supportedModes.includes(fulltextPredicate.mode)) {
|
|
2781
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2782
|
+
`Fulltext query mode "${fulltextPredicate.mode}" is not supported by the "${strategy.name}" strategy. Supported modes: ${strategy.supportedModes.join(", ")}.`
|
|
2783
|
+
);
|
|
2784
|
+
}
|
|
2785
|
+
if (!Number.isFinite(fulltextPredicate.limit) || fulltextPredicate.limit <= 0) {
|
|
2786
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2787
|
+
`Fulltext match limit must be a positive finite number, got ${String(fulltextPredicate.limit)}`
|
|
2788
|
+
);
|
|
2789
|
+
}
|
|
2790
|
+
const { minScore } = fulltextPredicate;
|
|
2791
|
+
if (minScore !== void 0 && !Number.isFinite(minScore)) {
|
|
2792
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2793
|
+
`Fulltext minScore must be a finite number, got ${String(minScore)}`
|
|
2794
|
+
);
|
|
2795
|
+
}
|
|
2796
|
+
return { fulltextPredicate };
|
|
2797
|
+
}
|
|
2798
|
+
function resolveFulltextAwareLimit(astLimit, fulltextPredicate) {
|
|
2799
|
+
if (fulltextPredicate === void 0) {
|
|
2800
|
+
return astLimit;
|
|
2801
|
+
}
|
|
2802
|
+
if (astLimit === void 0) {
|
|
2803
|
+
return fulltextPredicate.limit;
|
|
2804
|
+
}
|
|
2805
|
+
return Math.min(astLimit, fulltextPredicate.limit);
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
// src/query/compiler/passes/fusion.ts
|
|
2809
|
+
function runFusionConfigPass(ast, vectorPredicate, fulltextPredicate) {
|
|
2810
|
+
const fusion = ast.fusion;
|
|
2811
|
+
if (fusion === void 0) return { fusion: void 0 };
|
|
2812
|
+
if (vectorPredicate === void 0 || fulltextPredicate === void 0) {
|
|
2813
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2814
|
+
`.fuseWith() requires both a .similarTo() and a .$fulltext.matches() predicate in the same query. Remove .fuseWith(), or add the missing predicate.`
|
|
2815
|
+
);
|
|
2816
|
+
}
|
|
2817
|
+
if (vectorPredicate.field.alias !== fulltextPredicate.field.alias) {
|
|
2818
|
+
throw new chunkO5PST6TB_cjs.UnsupportedPredicateError(
|
|
2819
|
+
`.fuseWith() requires .similarTo() and .$fulltext.matches() to target the same node alias. Got vector=${vectorPredicate.field.alias}, fulltext=${fulltextPredicate.field.alias}.`
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
return { fusion };
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2425
2825
|
// src/query/compiler/passes/recursive.ts
|
|
2426
2826
|
function runRecursiveTraversalSelectionPass(ast) {
|
|
2427
2827
|
const variableLengthTraversal = ast.traversals.find(
|
|
@@ -2691,6 +3091,14 @@ function lowerStandardQueryToLogicalPlanNode(input) {
|
|
|
2691
3091
|
predicate: input.vectorPredicate
|
|
2692
3092
|
};
|
|
2693
3093
|
}
|
|
3094
|
+
if (input.fulltextPredicate !== void 0) {
|
|
3095
|
+
currentNode = {
|
|
3096
|
+
id: nextPlanNodeId(),
|
|
3097
|
+
input: currentNode,
|
|
3098
|
+
op: "fulltext_match",
|
|
3099
|
+
predicate: input.fulltextPredicate
|
|
3100
|
+
};
|
|
3101
|
+
}
|
|
2694
3102
|
return appendAggregateSortLimitAndProjectNodes(
|
|
2695
3103
|
currentNode,
|
|
2696
3104
|
ast,
|
|
@@ -2768,17 +3176,30 @@ function lowerComposableQueryToLogicalPlanNode(query, dialect, graphId, nextPlan
|
|
|
2768
3176
|
nextPlanNodeId
|
|
2769
3177
|
});
|
|
2770
3178
|
}
|
|
3179
|
+
const dialectAdapter = chunk3JK66E3I_cjs.getDialect(dialect);
|
|
2771
3180
|
const vectorPredicate = runVectorPredicatePass(
|
|
2772
3181
|
query,
|
|
2773
|
-
|
|
3182
|
+
dialectAdapter
|
|
2774
3183
|
).vectorPredicate;
|
|
2775
|
-
const
|
|
3184
|
+
const fulltextPredicate = runFulltextPredicatePass(
|
|
3185
|
+
query,
|
|
3186
|
+
dialectAdapter
|
|
3187
|
+
).fulltextPredicate;
|
|
3188
|
+
const limitAfterVector = resolveVectorAwareLimit(
|
|
3189
|
+
query.limit,
|
|
3190
|
+
vectorPredicate
|
|
3191
|
+
);
|
|
3192
|
+
const effectiveLimit = resolveFulltextAwareLimit(
|
|
3193
|
+
limitAfterVector,
|
|
3194
|
+
fulltextPredicate
|
|
3195
|
+
);
|
|
2776
3196
|
const loweringInput = {
|
|
2777
3197
|
ast: query,
|
|
2778
3198
|
graphId,
|
|
2779
3199
|
nextPlanNodeId,
|
|
2780
3200
|
...effectiveLimit === void 0 ? {} : { effectiveLimit },
|
|
2781
|
-
...vectorPredicate === void 0 ? {} : { vectorPredicate }
|
|
3201
|
+
...vectorPredicate === void 0 ? {} : { vectorPredicate },
|
|
3202
|
+
...fulltextPredicate === void 0 ? {} : { fulltextPredicate }
|
|
2782
3203
|
};
|
|
2783
3204
|
return lowerStandardQueryToLogicalPlanNode(loweringInput);
|
|
2784
3205
|
}
|
|
@@ -3285,10 +3706,10 @@ function compileRecursiveProjection(ast, traversal, dialect) {
|
|
|
3285
3706
|
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_deleted_at`
|
|
3286
3707
|
];
|
|
3287
3708
|
if (vl.depthAlias !== void 0) {
|
|
3288
|
-
fields.push(drizzleOrm.sql`depth AS ${
|
|
3709
|
+
fields.push(drizzleOrm.sql`depth AS ${quoteIdentifier2(vl.depthAlias)}`);
|
|
3289
3710
|
}
|
|
3290
3711
|
if (vl.pathAlias !== void 0) {
|
|
3291
|
-
fields.push(drizzleOrm.sql`path AS ${
|
|
3712
|
+
fields.push(drizzleOrm.sql`path AS ${quoteIdentifier2(vl.pathAlias)}`);
|
|
3292
3713
|
}
|
|
3293
3714
|
return drizzleOrm.sql.join(fields, drizzleOrm.sql`, `);
|
|
3294
3715
|
}
|
|
@@ -3302,23 +3723,23 @@ function compileRecursiveSelectiveProjection(fields, ast, traversal, dialect) {
|
|
|
3302
3723
|
}
|
|
3303
3724
|
if (field2.isSystemField) {
|
|
3304
3725
|
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
3305
|
-
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${
|
|
3726
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier2(field2.outputName)}`;
|
|
3306
3727
|
}
|
|
3307
3728
|
const column = drizzleOrm.sql.raw(`${field2.alias}_props`);
|
|
3308
3729
|
const extracted = compileTypedJsonExtract({
|
|
3309
3730
|
column,
|
|
3310
3731
|
dialect,
|
|
3311
|
-
pointer:
|
|
3732
|
+
pointer: chunkUVZHTBZ5_cjs.jsonPointer([field2.field]),
|
|
3312
3733
|
valueType: field2.valueType
|
|
3313
3734
|
});
|
|
3314
|
-
return drizzleOrm.sql`${extracted} AS ${
|
|
3735
|
+
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier2(field2.outputName)}`;
|
|
3315
3736
|
});
|
|
3316
3737
|
const vl = traversal.variableLength;
|
|
3317
3738
|
if (vl.depthAlias !== void 0) {
|
|
3318
|
-
columns.push(drizzleOrm.sql`depth AS ${
|
|
3739
|
+
columns.push(drizzleOrm.sql`depth AS ${quoteIdentifier2(vl.depthAlias)}`);
|
|
3319
3740
|
}
|
|
3320
3741
|
if (vl.pathAlias !== void 0) {
|
|
3321
|
-
columns.push(drizzleOrm.sql`path AS ${
|
|
3742
|
+
columns.push(drizzleOrm.sql`path AS ${quoteIdentifier2(vl.pathAlias)}`);
|
|
3322
3743
|
}
|
|
3323
3744
|
return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
|
|
3324
3745
|
}
|
|
@@ -3355,43 +3776,6 @@ function compileLimitOffset(ast) {
|
|
|
3355
3776
|
}
|
|
3356
3777
|
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
3357
3778
|
}
|
|
3358
|
-
var DEFAULT_TABLE_NAMES = {
|
|
3359
|
-
nodes: "typegraph_nodes",
|
|
3360
|
-
edges: "typegraph_edges",
|
|
3361
|
-
embeddings: "typegraph_node_embeddings"
|
|
3362
|
-
};
|
|
3363
|
-
var VALID_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_$]*$/i;
|
|
3364
|
-
function validateTableName(name, label) {
|
|
3365
|
-
if (!name || name.length === 0) {
|
|
3366
|
-
throw new chunkO5PST6TB_cjs.ConfigurationError(`${label} table name cannot be empty`);
|
|
3367
|
-
}
|
|
3368
|
-
if (name.length > chunkMME3H4ZF_cjs.MAX_PG_IDENTIFIER_LENGTH) {
|
|
3369
|
-
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
3370
|
-
`${label} table name exceeds maximum length of ${chunkMME3H4ZF_cjs.MAX_PG_IDENTIFIER_LENGTH} characters`
|
|
3371
|
-
);
|
|
3372
|
-
}
|
|
3373
|
-
if (!VALID_IDENTIFIER_PATTERN.test(name)) {
|
|
3374
|
-
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
3375
|
-
`${label} table name "${name}" is not a valid SQL identifier. Table names must start with a letter or underscore and contain only letters, digits, underscores, or dollar signs.`
|
|
3376
|
-
);
|
|
3377
|
-
}
|
|
3378
|
-
}
|
|
3379
|
-
function quoteIdentifier2(name) {
|
|
3380
|
-
return `"${name.replaceAll('"', '""')}"`;
|
|
3381
|
-
}
|
|
3382
|
-
function createSqlSchema(names = {}) {
|
|
3383
|
-
const tables = { ...DEFAULT_TABLE_NAMES, ...names };
|
|
3384
|
-
validateTableName(tables.nodes, "nodes");
|
|
3385
|
-
validateTableName(tables.edges, "edges");
|
|
3386
|
-
validateTableName(tables.embeddings, "embeddings");
|
|
3387
|
-
return {
|
|
3388
|
-
tables,
|
|
3389
|
-
nodesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.nodes)),
|
|
3390
|
-
edgesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.edges)),
|
|
3391
|
-
embeddingsTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.embeddings))
|
|
3392
|
-
};
|
|
3393
|
-
}
|
|
3394
|
-
var DEFAULT_SQL_SCHEMA = createSqlSchema();
|
|
3395
3779
|
|
|
3396
3780
|
// src/query/execution/value-decoder.ts
|
|
3397
3781
|
function nullToUndefined(value) {
|
|
@@ -3622,9 +4006,9 @@ function truncateToBytes(value, maxBytes) {
|
|
|
3622
4006
|
}
|
|
3623
4007
|
function projectionAlias(entityPrefix, kind, field2) {
|
|
3624
4008
|
const prefix = entityPrefix === "node" ? "sg_n" : "sg_e";
|
|
3625
|
-
const hash =
|
|
4009
|
+
const hash = chunk3JK66E3I_cjs.fnv1aBase36(`${kind}\0${field2}`);
|
|
3626
4010
|
const fixedBytes = prefix.length + 1 + 1 + hash.length;
|
|
3627
|
-
const maxKindBytes =
|
|
4011
|
+
const maxKindBytes = chunk3JK66E3I_cjs.MAX_PG_IDENTIFIER_LENGTH - fixedBytes;
|
|
3628
4012
|
const truncatedKind = truncateToBytes(kind, maxKindBytes);
|
|
3629
4013
|
return `${prefix}_${truncatedKind}_${hash}`;
|
|
3630
4014
|
}
|
|
@@ -3696,12 +4080,7 @@ async function executeSubgraph(params) {
|
|
|
3696
4080
|
for (const row of edgeRows) {
|
|
3697
4081
|
const edge = mapSubgraphEdgeRow(row, edgeProjectionPlan);
|
|
3698
4082
|
insertAdjacencyEntry(adjacency, edge.fromId, edge.kind, edge);
|
|
3699
|
-
insertAdjacencyEntry(
|
|
3700
|
-
reverseAdjacency,
|
|
3701
|
-
edge.toId,
|
|
3702
|
-
edge.kind,
|
|
3703
|
-
edge
|
|
3704
|
-
);
|
|
4083
|
+
insertAdjacencyEntry(reverseAdjacency, edge.toId, edge.kind, edge);
|
|
3705
4084
|
}
|
|
3706
4085
|
const root = nodesMap.get(ctx.rootId);
|
|
3707
4086
|
return {
|
|
@@ -3727,7 +4106,7 @@ function getSubgraphSchemaIntrospector(graph) {
|
|
|
3727
4106
|
{ schema: definition.type.schema }
|
|
3728
4107
|
])
|
|
3729
4108
|
);
|
|
3730
|
-
const introspector =
|
|
4109
|
+
const introspector = chunkUVZHTBZ5_cjs.createSchemaIntrospector(nodeKinds, edgeKinds);
|
|
3731
4110
|
introspectorCache.set(graph, introspector);
|
|
3732
4111
|
return introspector;
|
|
3733
4112
|
}
|
|
@@ -3871,11 +4250,11 @@ function buildProjectedPropertyColumns(alias, plan, dialect) {
|
|
|
3871
4250
|
const extracted = compileTypedJsonExtract({
|
|
3872
4251
|
column: drizzleOrm.sql.raw(`${alias}.props`),
|
|
3873
4252
|
dialect,
|
|
3874
|
-
pointer:
|
|
4253
|
+
pointer: chunkUVZHTBZ5_cjs.jsonPointer([fieldPlan.field]),
|
|
3875
4254
|
valueType: fieldPlan.typeInfo?.valueType
|
|
3876
4255
|
});
|
|
3877
4256
|
columns.push(
|
|
3878
|
-
drizzleOrm.sql`CASE WHEN ${drizzleOrm.sql.raw(alias)}.kind = ${kind} THEN ${extracted} ELSE NULL END AS ${
|
|
4257
|
+
drizzleOrm.sql`CASE WHEN ${drizzleOrm.sql.raw(alias)}.kind = ${kind} THEN ${extracted} ELSE NULL END AS ${quoteIdentifier2(fieldPlan.outputName)}`
|
|
3879
4258
|
);
|
|
3880
4259
|
}
|
|
3881
4260
|
}
|
|
@@ -3935,22 +4314,12 @@ function mapSubgraphEdgeRow(row, projectionPlan) {
|
|
|
3935
4314
|
fromId: row.from_id,
|
|
3936
4315
|
toKind: row.to_kind,
|
|
3937
4316
|
toId: row.to_id
|
|
3938
|
-
};
|
|
3939
|
-
if (kindPlan.includeMeta) {
|
|
3940
|
-
projectedEdge.meta = rowToEdgeMeta(row);
|
|
3941
|
-
}
|
|
3942
|
-
applyProjectedFields(projectedEdge, row, kindPlan);
|
|
3943
|
-
return projectedEdge;
|
|
3944
|
-
}
|
|
3945
|
-
|
|
3946
|
-
// src/query/ast.ts
|
|
3947
|
-
function mergeEdgeKinds(traversal) {
|
|
3948
|
-
const inverse = traversal.inverseEdgeKinds;
|
|
3949
|
-
if (inverse === void 0 || inverse.length === 0) return traversal.edgeKinds;
|
|
3950
|
-
return [
|
|
3951
|
-
...traversal.edgeKinds,
|
|
3952
|
-
...inverse.filter((kind) => !traversal.edgeKinds.includes(kind))
|
|
3953
|
-
];
|
|
4317
|
+
};
|
|
4318
|
+
if (kindPlan.includeMeta) {
|
|
4319
|
+
projectedEdge.meta = rowToEdgeMeta(row);
|
|
4320
|
+
}
|
|
4321
|
+
applyProjectedFields(projectedEdge, row, kindPlan);
|
|
4322
|
+
return projectedEdge;
|
|
3954
4323
|
}
|
|
3955
4324
|
var OPERATOR_MAP = {
|
|
3956
4325
|
union: "UNION",
|
|
@@ -4108,6 +4477,9 @@ function validateSqliteSetOpLeaf(ast) {
|
|
|
4108
4477
|
if (hasVectorSimilarityPredicates(ast)) {
|
|
4109
4478
|
unsupported.push("vector similarity predicates");
|
|
4110
4479
|
}
|
|
4480
|
+
if (hasFulltextMatchPredicates(ast)) {
|
|
4481
|
+
unsupported.push("fulltext match predicates");
|
|
4482
|
+
}
|
|
4111
4483
|
if (ast.groupBy !== void 0) {
|
|
4112
4484
|
unsupported.push("GROUP BY");
|
|
4113
4485
|
}
|
|
@@ -4157,7 +4529,42 @@ function hasVectorSimilarityInExpression(expr) {
|
|
|
4157
4529
|
case "between":
|
|
4158
4530
|
case "array_op":
|
|
4159
4531
|
case "object_op":
|
|
4160
|
-
case "aggregate_comparison":
|
|
4532
|
+
case "aggregate_comparison":
|
|
4533
|
+
case "fulltext_match": {
|
|
4534
|
+
return false;
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
}
|
|
4538
|
+
return false;
|
|
4539
|
+
}
|
|
4540
|
+
function hasFulltextMatchPredicates(ast) {
|
|
4541
|
+
return ast.predicates.some(
|
|
4542
|
+
(predicate2) => hasFulltextMatchInExpression(predicate2.expression)
|
|
4543
|
+
);
|
|
4544
|
+
}
|
|
4545
|
+
function hasFulltextMatchInExpression(expr) {
|
|
4546
|
+
if ("__type" in expr) {
|
|
4547
|
+
switch (expr.__type) {
|
|
4548
|
+
case "and":
|
|
4549
|
+
case "or": {
|
|
4550
|
+
return expr.predicates.some((p) => hasFulltextMatchInExpression(p));
|
|
4551
|
+
}
|
|
4552
|
+
case "not": {
|
|
4553
|
+
return hasFulltextMatchInExpression(expr.predicate);
|
|
4554
|
+
}
|
|
4555
|
+
case "fulltext_match": {
|
|
4556
|
+
return true;
|
|
4557
|
+
}
|
|
4558
|
+
case "exists":
|
|
4559
|
+
case "in_subquery":
|
|
4560
|
+
case "comparison":
|
|
4561
|
+
case "string_op":
|
|
4562
|
+
case "null_check":
|
|
4563
|
+
case "between":
|
|
4564
|
+
case "array_op":
|
|
4565
|
+
case "object_op":
|
|
4566
|
+
case "aggregate_comparison":
|
|
4567
|
+
case "vector_similarity": {
|
|
4161
4568
|
return false;
|
|
4162
4569
|
}
|
|
4163
4570
|
}
|
|
@@ -4193,7 +4600,8 @@ function hasSubqueryInExpression(expr) {
|
|
|
4193
4600
|
case "array_op":
|
|
4194
4601
|
case "object_op":
|
|
4195
4602
|
case "aggregate_comparison":
|
|
4196
|
-
case "vector_similarity":
|
|
4603
|
+
case "vector_similarity":
|
|
4604
|
+
case "fulltext_match": {
|
|
4197
4605
|
return false;
|
|
4198
4606
|
}
|
|
4199
4607
|
}
|
|
@@ -4359,7 +4767,7 @@ function getLeftmostProjection(op) {
|
|
|
4359
4767
|
function normalizeFieldRefKey(field2) {
|
|
4360
4768
|
let pointer = field2.jsonPointer;
|
|
4361
4769
|
if (pointer === void 0 && field2.path.length > 1 && field2.path[0] === "props") {
|
|
4362
|
-
pointer =
|
|
4770
|
+
pointer = chunkUVZHTBZ5_cjs.jsonPointer(field2.path.slice(1));
|
|
4363
4771
|
}
|
|
4364
4772
|
const basePath = field2.path.length > 0 && field2.path[0] === "props" ? "props" : field2.path.join(".");
|
|
4365
4773
|
return `${field2.alias}:${basePath}:${pointer ?? ""}`;
|
|
@@ -4471,6 +4879,10 @@ function markPredicateFieldsAsRequired(requiredColumnsByAlias, expression) {
|
|
|
4471
4879
|
markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
|
|
4472
4880
|
return;
|
|
4473
4881
|
}
|
|
4882
|
+
case "fulltext_match": {
|
|
4883
|
+
markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
|
|
4884
|
+
return;
|
|
4885
|
+
}
|
|
4474
4886
|
case "exists": {
|
|
4475
4887
|
return;
|
|
4476
4888
|
}
|
|
@@ -4535,7 +4947,8 @@ function hasIdEqualityPredicate(expression, alias) {
|
|
|
4535
4947
|
case "aggregate_comparison":
|
|
4536
4948
|
case "exists":
|
|
4537
4949
|
case "in_subquery":
|
|
4538
|
-
case "vector_similarity":
|
|
4950
|
+
case "vector_similarity":
|
|
4951
|
+
case "fulltext_match": {
|
|
4539
4952
|
return false;
|
|
4540
4953
|
}
|
|
4541
4954
|
}
|
|
@@ -4576,10 +4989,13 @@ function resolveTraversalCteLimit(ast, predicateIndex) {
|
|
|
4576
4989
|
);
|
|
4577
4990
|
return Math.max(ast.limit, pushdownLimit);
|
|
4578
4991
|
}
|
|
4579
|
-
function canCollapseSelectiveTraversalRowset(ast, vectorPredicate) {
|
|
4992
|
+
function canCollapseSelectiveTraversalRowset(ast, vectorPredicate, fulltextPredicate) {
|
|
4580
4993
|
if (vectorPredicate !== void 0) {
|
|
4581
4994
|
return false;
|
|
4582
4995
|
}
|
|
4996
|
+
if (fulltextPredicate !== void 0) {
|
|
4997
|
+
return false;
|
|
4998
|
+
}
|
|
4583
4999
|
if (ast.traversals.length === 0) {
|
|
4584
5000
|
return false;
|
|
4585
5001
|
}
|
|
@@ -4619,6 +5035,8 @@ function runStandardQueryPassPipeline(ast, graphId, ctx) {
|
|
|
4619
5035
|
collapsedTraversalCteAlias: void 0,
|
|
4620
5036
|
ctx,
|
|
4621
5037
|
effectiveLimit: void 0,
|
|
5038
|
+
fulltextPredicate: void 0,
|
|
5039
|
+
fusion: void 0,
|
|
4622
5040
|
logicalPlan: void 0,
|
|
4623
5041
|
predicateIndex: buildPredicateIndex(ast),
|
|
4624
5042
|
requiredColumnsByAlias: void 0,
|
|
@@ -4640,6 +5058,39 @@ function runStandardQueryPassPipeline(ast, graphId, ctx) {
|
|
|
4640
5058
|
}
|
|
4641
5059
|
});
|
|
4642
5060
|
state = vectorPass.state;
|
|
5061
|
+
const fulltextPass = runCompilerPass(state, {
|
|
5062
|
+
name: "fulltext_predicate",
|
|
5063
|
+
execute(currentState) {
|
|
5064
|
+
return runFulltextPredicatePass(
|
|
5065
|
+
currentState.ast,
|
|
5066
|
+
currentState.ctx.dialect
|
|
5067
|
+
).fulltextPredicate;
|
|
5068
|
+
},
|
|
5069
|
+
update(currentState, fulltextPredicate) {
|
|
5070
|
+
return {
|
|
5071
|
+
...currentState,
|
|
5072
|
+
fulltextPredicate
|
|
5073
|
+
};
|
|
5074
|
+
}
|
|
5075
|
+
});
|
|
5076
|
+
state = fulltextPass.state;
|
|
5077
|
+
const fusionPass = runCompilerPass(state, {
|
|
5078
|
+
name: "fusion_config",
|
|
5079
|
+
execute(currentState) {
|
|
5080
|
+
return runFusionConfigPass(
|
|
5081
|
+
currentState.ast,
|
|
5082
|
+
currentState.vectorPredicate,
|
|
5083
|
+
currentState.fulltextPredicate
|
|
5084
|
+
).fusion;
|
|
5085
|
+
},
|
|
5086
|
+
update(currentState, fusion) {
|
|
5087
|
+
return {
|
|
5088
|
+
...currentState,
|
|
5089
|
+
fusion
|
|
5090
|
+
};
|
|
5091
|
+
}
|
|
5092
|
+
});
|
|
5093
|
+
state = fusionPass.state;
|
|
4643
5094
|
const temporalPass = runCompilerPass(state, {
|
|
4644
5095
|
name: "temporal_filters",
|
|
4645
5096
|
execute(currentState) {
|
|
@@ -4674,7 +5125,8 @@ function runStandardQueryPassPipeline(ast, graphId, ctx) {
|
|
|
4674
5125
|
execute(currentState) {
|
|
4675
5126
|
const shouldCollapseSelectiveTraversalRowset = canCollapseSelectiveTraversalRowset(
|
|
4676
5127
|
currentState.ast,
|
|
4677
|
-
currentState.vectorPredicate
|
|
5128
|
+
currentState.vectorPredicate,
|
|
5129
|
+
currentState.fulltextPredicate
|
|
4678
5130
|
);
|
|
4679
5131
|
const lastTraversal = currentState.ast.traversals.at(-1);
|
|
4680
5132
|
const collapsedTraversalCteAlias = shouldCollapseSelectiveTraversalRowset && lastTraversal !== void 0 ? `cte_${lastTraversal.nodeAlias}` : void 0;
|
|
@@ -4710,9 +5162,9 @@ function runStandardQueryPassPipeline(ast, graphId, ctx) {
|
|
|
4710
5162
|
state = traversalLimitPass.state;
|
|
4711
5163
|
state = {
|
|
4712
5164
|
...state,
|
|
4713
|
-
effectiveLimit:
|
|
4714
|
-
state.ast.limit,
|
|
4715
|
-
state.
|
|
5165
|
+
effectiveLimit: resolveFulltextAwareLimit(
|
|
5166
|
+
resolveVectorAwareLimit(state.ast.limit, state.vectorPredicate),
|
|
5167
|
+
state.fulltextPredicate
|
|
4716
5168
|
)
|
|
4717
5169
|
};
|
|
4718
5170
|
const logicalPlanPass = runCompilerPass(state, {
|
|
@@ -4729,7 +5181,8 @@ function runStandardQueryPassPipeline(ast, graphId, ctx) {
|
|
|
4729
5181
|
collapsedTraversalCteAlias: currentState.collapsedTraversalCteAlias
|
|
4730
5182
|
},
|
|
4731
5183
|
...currentState.effectiveLimit === void 0 ? {} : { effectiveLimit: currentState.effectiveLimit },
|
|
4732
|
-
...currentState.vectorPredicate === void 0 ? {} : { vectorPredicate: currentState.vectorPredicate }
|
|
5184
|
+
...currentState.vectorPredicate === void 0 ? {} : { vectorPredicate: currentState.vectorPredicate },
|
|
5185
|
+
...currentState.fulltextPredicate === void 0 ? {} : { fulltextPredicate: currentState.fulltextPredicate }
|
|
4733
5186
|
});
|
|
4734
5187
|
},
|
|
4735
5188
|
update(currentState, logicalPlan) {
|
|
@@ -4748,11 +5201,11 @@ function compileQuery(ast, graphId, options = "sqlite") {
|
|
|
4748
5201
|
const options_ = typeof options === "string" ? { dialect: options } : options;
|
|
4749
5202
|
const dialect = options_.dialect ?? "sqlite";
|
|
4750
5203
|
const schema = options_.schema ?? DEFAULT_SQL_SCHEMA;
|
|
4751
|
-
const adapter =
|
|
5204
|
+
const adapter = resolveDialectAdapter(dialect, options_.fulltextStrategy);
|
|
4752
5205
|
const ctx = {
|
|
4753
5206
|
dialect: adapter,
|
|
4754
5207
|
schema,
|
|
4755
|
-
compileQuery: (subAst, subGraphId) => compileQuery(subAst, subGraphId,
|
|
5208
|
+
compileQuery: (subAst, subGraphId) => compileQuery(subAst, subGraphId, propagateOptions(options_))
|
|
4756
5209
|
};
|
|
4757
5210
|
if (hasVariableLengthTraversal(ast)) {
|
|
4758
5211
|
const lowered = tryLowerSingleHopRecursiveTraversal(ast);
|
|
@@ -4788,15 +5241,29 @@ function compileSetOperation2(op, graphId, options = "sqlite") {
|
|
|
4788
5241
|
const options_ = typeof options === "string" ? { dialect: options } : options;
|
|
4789
5242
|
const dialect = options_.dialect ?? "sqlite";
|
|
4790
5243
|
const schema = options_.schema ?? DEFAULT_SQL_SCHEMA;
|
|
4791
|
-
const adapter =
|
|
5244
|
+
const adapter = resolveDialectAdapter(dialect, options_.fulltextStrategy);
|
|
4792
5245
|
return compileSetOperation(
|
|
4793
5246
|
op,
|
|
4794
5247
|
graphId,
|
|
4795
5248
|
adapter,
|
|
4796
5249
|
schema,
|
|
4797
|
-
(ast, gid) => compileQuery(ast, gid,
|
|
5250
|
+
(ast, gid) => compileQuery(ast, gid, propagateOptions(options_))
|
|
4798
5251
|
);
|
|
4799
5252
|
}
|
|
5253
|
+
function resolveDialectAdapter(dialect, fulltextStrategy) {
|
|
5254
|
+
const baseAdapter = chunk3JK66E3I_cjs.getDialect(dialect);
|
|
5255
|
+
if (fulltextStrategy === void 0 || fulltextStrategy === baseAdapter.fulltext) {
|
|
5256
|
+
return baseAdapter;
|
|
5257
|
+
}
|
|
5258
|
+
return { ...baseAdapter, fulltext: fulltextStrategy };
|
|
5259
|
+
}
|
|
5260
|
+
function propagateOptions(options_) {
|
|
5261
|
+
return {
|
|
5262
|
+
dialect: options_.dialect ?? "sqlite",
|
|
5263
|
+
...options_.schema === void 0 ? {} : { schema: options_.schema },
|
|
5264
|
+
...options_.fulltextStrategy === void 0 ? {} : { fulltextStrategy: options_.fulltextStrategy }
|
|
5265
|
+
};
|
|
5266
|
+
}
|
|
4800
5267
|
function resolveCountAggregateFastPath(ast) {
|
|
4801
5268
|
if (ast.traversals.length !== 1) {
|
|
4802
5269
|
return void 0;
|
|
@@ -4818,8 +5285,10 @@ function resolveCountAggregateFastPath(ast) {
|
|
|
4818
5285
|
if (groupField.alias !== ast.start.alias || !isIdFieldRef(groupField)) {
|
|
4819
5286
|
return void 0;
|
|
4820
5287
|
}
|
|
4821
|
-
let
|
|
4822
|
-
let
|
|
5288
|
+
let requiresNodeCount = false;
|
|
5289
|
+
let requiresNodeCountDistinct = false;
|
|
5290
|
+
let requiresEdgeCount = false;
|
|
5291
|
+
let requiresEdgeCountDistinct = false;
|
|
4823
5292
|
for (const projectedField of ast.projection.fields) {
|
|
4824
5293
|
const source = projectedField.source;
|
|
4825
5294
|
if (!isAggregateExpr(source)) {
|
|
@@ -4828,26 +5297,35 @@ function resolveCountAggregateFastPath(ast) {
|
|
|
4828
5297
|
}
|
|
4829
5298
|
continue;
|
|
4830
5299
|
}
|
|
4831
|
-
if (
|
|
5300
|
+
if (!isIdFieldRef(source.field)) {
|
|
5301
|
+
return void 0;
|
|
5302
|
+
}
|
|
5303
|
+
const isNodeTarget = source.field.alias === traversal.nodeAlias;
|
|
5304
|
+
const isEdgeTarget = source.field.alias === traversal.edgeAlias;
|
|
5305
|
+
if (!isNodeTarget && !isEdgeTarget) {
|
|
4832
5306
|
return void 0;
|
|
4833
5307
|
}
|
|
4834
5308
|
if (source.function === "count") {
|
|
4835
|
-
|
|
5309
|
+
if (isNodeTarget) requiresNodeCount = true;
|
|
5310
|
+
else requiresEdgeCount = true;
|
|
4836
5311
|
continue;
|
|
4837
5312
|
}
|
|
4838
5313
|
if (source.function === "countDistinct") {
|
|
4839
|
-
|
|
5314
|
+
if (isNodeTarget) requiresNodeCountDistinct = true;
|
|
5315
|
+
else requiresEdgeCountDistinct = true;
|
|
4840
5316
|
continue;
|
|
4841
5317
|
}
|
|
4842
5318
|
return void 0;
|
|
4843
5319
|
}
|
|
4844
|
-
if (!
|
|
5320
|
+
if (!requiresNodeCount && !requiresNodeCountDistinct && !requiresEdgeCount && !requiresEdgeCountDistinct) {
|
|
4845
5321
|
return void 0;
|
|
4846
5322
|
}
|
|
4847
5323
|
return {
|
|
4848
5324
|
traversal,
|
|
4849
|
-
|
|
4850
|
-
|
|
5325
|
+
requiresNodeCount,
|
|
5326
|
+
requiresNodeCountDistinct,
|
|
5327
|
+
requiresEdgeCount,
|
|
5328
|
+
requiresEdgeCountDistinct
|
|
4851
5329
|
};
|
|
4852
5330
|
}
|
|
4853
5331
|
function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredColumnsByAlias, predicateIndex, temporalFilterPass) {
|
|
@@ -4855,15 +5333,23 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
|
|
|
4855
5333
|
if (!plan) {
|
|
4856
5334
|
return void 0;
|
|
4857
5335
|
}
|
|
4858
|
-
const {
|
|
5336
|
+
const {
|
|
5337
|
+
traversal,
|
|
5338
|
+
requiresNodeCount,
|
|
5339
|
+
requiresNodeCountDistinct,
|
|
5340
|
+
requiresEdgeCount,
|
|
5341
|
+
requiresEdgeCountDistinct
|
|
5342
|
+
} = plan;
|
|
4859
5343
|
const { dialect } = ctx;
|
|
4860
5344
|
const startAlias = ast.start.alias;
|
|
4861
5345
|
const previousAlias = traversal.joinFromAlias;
|
|
4862
5346
|
const previousAliasIdColumn = `${previousAlias}_id`;
|
|
4863
5347
|
const previousAliasKindColumn = `${previousAlias}_kind`;
|
|
4864
5348
|
const countCteAlias = `cte_${traversal.nodeAlias}_counts`;
|
|
4865
|
-
const
|
|
4866
|
-
const
|
|
5349
|
+
const nodeCountColumn = `${traversal.nodeAlias}_count`;
|
|
5350
|
+
const nodeCountDistinctColumn = `${traversal.nodeAlias}_count_distinct`;
|
|
5351
|
+
const edgeCountColumn = `${traversal.edgeAlias}_count`;
|
|
5352
|
+
const edgeCountDistinctColumn = `${traversal.edgeAlias}_count_distinct`;
|
|
4867
5353
|
const previousNodeKinds = getNodeKindsForAlias(ast, traversal.joinFromAlias);
|
|
4868
5354
|
const edgeKinds = [...new Set(traversal.edgeKinds)];
|
|
4869
5355
|
const nodeKinds = traversal.nodeKinds;
|
|
@@ -4889,34 +5375,68 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
|
|
|
4889
5375
|
const targetField = traversal.direction === "out" ? "to_id" : "from_id";
|
|
4890
5376
|
const joinKindField = traversal.direction === "out" ? "from_kind" : "to_kind";
|
|
4891
5377
|
const targetKindField = traversal.direction === "out" ? "to_kind" : "from_kind";
|
|
5378
|
+
const hasNodePredicates = nodePredicateClauses.length > 0;
|
|
5379
|
+
const requiresNodeJoin = requiresNodeCount || requiresNodeCountDistinct || hasNodePredicates;
|
|
5380
|
+
const useInnerJoin = hasNodePredicates;
|
|
4892
5381
|
const whereClauses = [
|
|
4893
5382
|
drizzleOrm.sql`e.graph_id = ${graphId}`,
|
|
4894
5383
|
compileKindFilter(drizzleOrm.sql.raw("e.kind"), edgeKinds),
|
|
4895
5384
|
compileKindFilter(drizzleOrm.sql.raw(`e.${joinKindField}`), previousNodeKinds),
|
|
4896
5385
|
compileKindFilter(drizzleOrm.sql.raw(`e.${targetKindField}`), nodeKinds),
|
|
4897
|
-
compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds),
|
|
4898
5386
|
edgeTemporalFilter,
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
...
|
|
5387
|
+
...edgePredicateClauses,
|
|
5388
|
+
// INNER JOIN mode: node-side filters in WHERE constrain every aggregate.
|
|
5389
|
+
...requiresNodeJoin && useInnerJoin ? [
|
|
5390
|
+
compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds),
|
|
5391
|
+
nodeTemporalFilter,
|
|
5392
|
+
...nodePredicateClauses
|
|
5393
|
+
] : []
|
|
4902
5394
|
];
|
|
5395
|
+
const nodeJoinOnClauses = requiresNodeJoin ? useInnerJoin ? (
|
|
5396
|
+
// INNER JOIN: only the key conditions; filters live in WHERE.
|
|
5397
|
+
[
|
|
5398
|
+
drizzleOrm.sql`n.graph_id = e.graph_id`,
|
|
5399
|
+
drizzleOrm.sql`n.id = e.${drizzleOrm.sql.raw(targetField)}`,
|
|
5400
|
+
drizzleOrm.sql`n.kind = e.${drizzleOrm.sql.raw(targetKindField)}`
|
|
5401
|
+
]
|
|
5402
|
+
) : [
|
|
5403
|
+
drizzleOrm.sql`n.graph_id = e.graph_id`,
|
|
5404
|
+
drizzleOrm.sql`n.id = e.${drizzleOrm.sql.raw(targetField)}`,
|
|
5405
|
+
drizzleOrm.sql`n.kind = e.${drizzleOrm.sql.raw(targetKindField)}`,
|
|
5406
|
+
compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds),
|
|
5407
|
+
nodeTemporalFilter
|
|
5408
|
+
] : [];
|
|
4903
5409
|
const aggregateColumns = [];
|
|
4904
|
-
if (
|
|
4905
|
-
aggregateColumns.push(drizzleOrm.sql`COUNT(n.id) AS ${drizzleOrm.sql.raw(
|
|
5410
|
+
if (requiresNodeCount) {
|
|
5411
|
+
aggregateColumns.push(drizzleOrm.sql`COUNT(n.id) AS ${drizzleOrm.sql.raw(nodeCountColumn)}`);
|
|
5412
|
+
}
|
|
5413
|
+
if (requiresNodeCountDistinct) {
|
|
5414
|
+
aggregateColumns.push(
|
|
5415
|
+
drizzleOrm.sql`COUNT(DISTINCT n.id) AS ${drizzleOrm.sql.raw(nodeCountDistinctColumn)}`
|
|
5416
|
+
);
|
|
4906
5417
|
}
|
|
4907
|
-
if (
|
|
5418
|
+
if (requiresEdgeCount) {
|
|
5419
|
+
aggregateColumns.push(drizzleOrm.sql`COUNT(e.id) AS ${drizzleOrm.sql.raw(edgeCountColumn)}`);
|
|
5420
|
+
}
|
|
5421
|
+
if (requiresEdgeCountDistinct) {
|
|
4908
5422
|
aggregateColumns.push(
|
|
4909
|
-
drizzleOrm.sql`COUNT(DISTINCT
|
|
5423
|
+
drizzleOrm.sql`COUNT(DISTINCT e.id) AS ${drizzleOrm.sql.raw(edgeCountDistinctColumn)}`
|
|
4910
5424
|
);
|
|
4911
5425
|
}
|
|
5426
|
+
const startCteLimit = traversal.optional && ast.orderBy === void 0 && ast.limit !== void 0 ? { limit: ast.limit, offset: ast.offset } : void 0;
|
|
4912
5427
|
const startCte = buildStandardStartCte({
|
|
4913
5428
|
ast,
|
|
4914
5429
|
ctx,
|
|
4915
5430
|
graphId,
|
|
4916
5431
|
predicateIndex,
|
|
4917
5432
|
requiredColumnsByAlias,
|
|
4918
|
-
temporalFilterPass
|
|
5433
|
+
temporalFilterPass,
|
|
5434
|
+
...startCteLimit === void 0 ? {} : { limitOffset: startCteLimit }
|
|
4919
5435
|
});
|
|
5436
|
+
const targetNodeJoinKeyword = useInnerJoin ? "JOIN" : "LEFT JOIN";
|
|
5437
|
+
const targetNodeJoin = requiresNodeJoin ? drizzleOrm.sql`
|
|
5438
|
+
${drizzleOrm.sql.raw(targetNodeJoinKeyword)} ${ctx.schema.nodesTable} n ON ${drizzleOrm.sql.join(nodeJoinOnClauses, drizzleOrm.sql` AND `)}
|
|
5439
|
+
` : drizzleOrm.sql``;
|
|
4920
5440
|
const countCte = drizzleOrm.sql`
|
|
4921
5441
|
${drizzleOrm.sql.raw(countCteAlias)} AS (
|
|
4922
5442
|
SELECT
|
|
@@ -4925,16 +5445,20 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
|
|
|
4925
5445
|
${drizzleOrm.sql.join(aggregateColumns, drizzleOrm.sql`, `)}
|
|
4926
5446
|
FROM cte_${drizzleOrm.sql.raw(previousAlias)}
|
|
4927
5447
|
JOIN ${ctx.schema.edgesTable} e ON cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasIdColumn)} = e.${drizzleOrm.sql.raw(joinField)}
|
|
4928
|
-
AND cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)} = e.${drizzleOrm.sql.raw(joinKindField)}
|
|
4929
|
-
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
4930
|
-
AND n.id = e.${drizzleOrm.sql.raw(targetField)}
|
|
4931
|
-
AND n.kind = e.${drizzleOrm.sql.raw(targetKindField)}
|
|
5448
|
+
AND cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)} = e.${drizzleOrm.sql.raw(joinKindField)}${targetNodeJoin}
|
|
4932
5449
|
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
|
|
4933
5450
|
GROUP BY
|
|
4934
5451
|
cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasIdColumn)},
|
|
4935
5452
|
cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)}
|
|
4936
5453
|
)
|
|
4937
5454
|
`;
|
|
5455
|
+
function resolveCountColumn(source) {
|
|
5456
|
+
const isEdge = source.field.alias === traversal.edgeAlias;
|
|
5457
|
+
if (source.function === "countDistinct") {
|
|
5458
|
+
return isEdge ? edgeCountDistinctColumn : nodeCountDistinctColumn;
|
|
5459
|
+
}
|
|
5460
|
+
return isEdge ? edgeCountColumn : nodeCountColumn;
|
|
5461
|
+
}
|
|
4938
5462
|
const projection = drizzleOrm.sql.join(
|
|
4939
5463
|
ast.projection.fields.map((projectedField) => {
|
|
4940
5464
|
const source = projectedField.source;
|
|
@@ -4945,12 +5469,12 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
|
|
|
4945
5469
|
source.valueType,
|
|
4946
5470
|
`cte_${source.alias}`
|
|
4947
5471
|
);
|
|
4948
|
-
return drizzleOrm.sql`${value} AS ${
|
|
5472
|
+
return drizzleOrm.sql`${value} AS ${quoteIdentifier2(projectedField.outputName)}`;
|
|
4949
5473
|
}
|
|
4950
|
-
const projectedCountColumn = source
|
|
5474
|
+
const projectedCountColumn = resolveCountColumn(source);
|
|
4951
5475
|
const countValue = drizzleOrm.sql`${drizzleOrm.sql.raw(countCteAlias)}.${drizzleOrm.sql.raw(projectedCountColumn)}`;
|
|
4952
5476
|
const aggregateValue = traversal.optional ? drizzleOrm.sql`COALESCE(${countValue}, 0)` : countValue;
|
|
4953
|
-
return drizzleOrm.sql`${aggregateValue} AS ${
|
|
5477
|
+
return drizzleOrm.sql`${aggregateValue} AS ${quoteIdentifier2(projectedField.outputName)}`;
|
|
4954
5478
|
}),
|
|
4955
5479
|
drizzleOrm.sql`, `
|
|
4956
5480
|
);
|
|
@@ -4962,19 +5486,29 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
|
|
|
4962
5486
|
AND ${drizzleOrm.sql.raw(countCteAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)} = cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)}
|
|
4963
5487
|
`;
|
|
4964
5488
|
const orderBy = buildStandardOrderBy({ ast, dialect });
|
|
4965
|
-
const
|
|
4966
|
-
|
|
4967
|
-
offset: ast.offset
|
|
4968
|
-
});
|
|
5489
|
+
const emittedLogicalPlan = startCteLimit === void 0 ? logicalPlan : stripLimitOffsetFromPlan(logicalPlan);
|
|
5490
|
+
const limitOffset = startCteLimit === void 0 ? buildLimitOffsetClause({ limit: ast.limit, offset: ast.offset }) : void 0;
|
|
4969
5491
|
return emitStandardQuerySql({
|
|
4970
5492
|
ctes: [startCte, countCte],
|
|
4971
5493
|
fromClause,
|
|
4972
5494
|
...orderBy === void 0 ? {} : { orderBy },
|
|
4973
5495
|
...limitOffset === void 0 ? {} : { limitOffset },
|
|
4974
|
-
logicalPlan,
|
|
5496
|
+
logicalPlan: emittedLogicalPlan,
|
|
4975
5497
|
projection
|
|
4976
5498
|
});
|
|
4977
5499
|
}
|
|
5500
|
+
function stripLimitOffsetFromPlan(plan) {
|
|
5501
|
+
return { ...plan, root: stripLimitOffsetFromPlanNode(plan.root) };
|
|
5502
|
+
}
|
|
5503
|
+
function stripLimitOffsetFromPlanNode(node) {
|
|
5504
|
+
if (node.op === "limit_offset") {
|
|
5505
|
+
return stripLimitOffsetFromPlanNode(node.input);
|
|
5506
|
+
}
|
|
5507
|
+
if ("input" in node) {
|
|
5508
|
+
return { ...node, input: stripLimitOffsetFromPlanNode(node.input) };
|
|
5509
|
+
}
|
|
5510
|
+
return node;
|
|
5511
|
+
}
|
|
4978
5512
|
var STANDARD_QUERY_STRATEGY_HANDLERS = {
|
|
4979
5513
|
cte_project: compileStandardQueryWithCteStrategy
|
|
4980
5514
|
};
|
|
@@ -4983,11 +5517,37 @@ function compileStandardQuery(ast, graphId, ctx) {
|
|
|
4983
5517
|
const handler = STANDARD_QUERY_STRATEGY_HANDLERS[strategy];
|
|
4984
5518
|
return handler(ast, graphId, ctx);
|
|
4985
5519
|
}
|
|
5520
|
+
function selectStandardOrderBy(input) {
|
|
5521
|
+
const {
|
|
5522
|
+
ast,
|
|
5523
|
+
collapsedTraversalCteAlias,
|
|
5524
|
+
dialect,
|
|
5525
|
+
fulltextPredicate,
|
|
5526
|
+
fusion,
|
|
5527
|
+
vectorPredicate
|
|
5528
|
+
} = input;
|
|
5529
|
+
if (vectorPredicate && fulltextPredicate) {
|
|
5530
|
+
return buildStandardHybridRrfOrderBy({ ast, dialect, fusion });
|
|
5531
|
+
}
|
|
5532
|
+
if (vectorPredicate) {
|
|
5533
|
+
return buildStandardVectorOrderBy({ ast, dialect });
|
|
5534
|
+
}
|
|
5535
|
+
if (fulltextPredicate) {
|
|
5536
|
+
return buildStandardFulltextOrderBy({ ast, dialect });
|
|
5537
|
+
}
|
|
5538
|
+
return buildStandardOrderBy({
|
|
5539
|
+
ast,
|
|
5540
|
+
...collapsedTraversalCteAlias === void 0 ? {} : { collapsedTraversalCteAlias },
|
|
5541
|
+
dialect
|
|
5542
|
+
});
|
|
5543
|
+
}
|
|
4986
5544
|
function compileStandardQueryWithCteStrategy(ast, graphId, ctx) {
|
|
4987
5545
|
const { dialect } = ctx;
|
|
4988
5546
|
const {
|
|
4989
5547
|
collapsedTraversalCteAlias,
|
|
4990
5548
|
effectiveLimit,
|
|
5549
|
+
fulltextPredicate,
|
|
5550
|
+
fusion,
|
|
4991
5551
|
logicalPlan,
|
|
4992
5552
|
predicateIndex,
|
|
4993
5553
|
requiredColumnsByAlias,
|
|
@@ -5008,7 +5568,7 @@ function compileStandardQueryWithCteStrategy(ast, graphId, ctx) {
|
|
|
5008
5568
|
{ phase: "standard-pass-pipeline" }
|
|
5009
5569
|
);
|
|
5010
5570
|
}
|
|
5011
|
-
if (!vectorPredicate) {
|
|
5571
|
+
if (!vectorPredicate && !fulltextPredicate) {
|
|
5012
5572
|
const fastPathSql = compileCountAggregateFastPath(
|
|
5013
5573
|
ast,
|
|
5014
5574
|
graphId,
|
|
@@ -5054,7 +5614,29 @@ function compileStandardQueryWithCteStrategy(ast, graphId, ctx) {
|
|
|
5054
5614
|
);
|
|
5055
5615
|
}
|
|
5056
5616
|
if (vectorPredicate) {
|
|
5057
|
-
|
|
5617
|
+
const nodeKinds = getNodeKindsForAlias(ast, vectorPredicate.field.alias);
|
|
5618
|
+
ctes.push(
|
|
5619
|
+
buildStandardEmbeddingsCte({
|
|
5620
|
+
ctx,
|
|
5621
|
+
graphId,
|
|
5622
|
+
nodeKinds,
|
|
5623
|
+
vectorPredicate
|
|
5624
|
+
})
|
|
5625
|
+
);
|
|
5626
|
+
}
|
|
5627
|
+
if (fulltextPredicate) {
|
|
5628
|
+
const nodeKinds = getNodeKindsForAlias(ast, fulltextPredicate.field.alias);
|
|
5629
|
+
ctes.push(
|
|
5630
|
+
buildStandardFulltextCte({
|
|
5631
|
+
ctx,
|
|
5632
|
+
fulltextPredicate,
|
|
5633
|
+
graphId,
|
|
5634
|
+
nodeKinds
|
|
5635
|
+
})
|
|
5636
|
+
);
|
|
5637
|
+
}
|
|
5638
|
+
if (getHybridTargetAlias(vectorPredicate, fulltextPredicate) !== void 0) {
|
|
5639
|
+
ctes.push(buildStandardHybridCandidateCte());
|
|
5058
5640
|
}
|
|
5059
5641
|
const projection = buildStandardProjection({
|
|
5060
5642
|
ast,
|
|
@@ -5064,14 +5646,18 @@ function compileStandardQueryWithCteStrategy(ast, graphId, ctx) {
|
|
|
5064
5646
|
const fromClause = buildStandardFromClause({
|
|
5065
5647
|
ast,
|
|
5066
5648
|
...collapsedTraversalCteAlias === void 0 ? {} : { collapsedTraversalCteAlias },
|
|
5067
|
-
...vectorPredicate === void 0 ? {} : { vectorPredicate }
|
|
5649
|
+
...vectorPredicate === void 0 ? {} : { vectorPredicate },
|
|
5650
|
+
...fulltextPredicate === void 0 ? {} : { fulltextPredicate }
|
|
5068
5651
|
});
|
|
5069
5652
|
const groupBy = buildStandardGroupBy({ ast, dialect });
|
|
5070
5653
|
const having2 = buildStandardHaving({ ast, ctx });
|
|
5071
|
-
const orderBy =
|
|
5654
|
+
const orderBy = selectStandardOrderBy({
|
|
5072
5655
|
ast,
|
|
5073
|
-
|
|
5074
|
-
dialect
|
|
5656
|
+
collapsedTraversalCteAlias,
|
|
5657
|
+
dialect,
|
|
5658
|
+
fulltextPredicate,
|
|
5659
|
+
fusion,
|
|
5660
|
+
vectorPredicate
|
|
5075
5661
|
});
|
|
5076
5662
|
const limitOffset = buildLimitOffsetClause({
|
|
5077
5663
|
limit: effectiveLimit,
|
|
@@ -5193,7 +5779,7 @@ function extractCursorValue(row, spec) {
|
|
|
5193
5779
|
current = record[segment];
|
|
5194
5780
|
}
|
|
5195
5781
|
if (jsonPointer2) {
|
|
5196
|
-
const segments =
|
|
5782
|
+
const segments = chunkUVZHTBZ5_cjs.parseJsonPointer(jsonPointer2);
|
|
5197
5783
|
for (const segment of segments) {
|
|
5198
5784
|
if (current === null || current === void 0) return void 0;
|
|
5199
5785
|
if (typeof current !== "object") return void 0;
|
|
@@ -5263,14 +5849,14 @@ function generateId() {
|
|
|
5263
5849
|
|
|
5264
5850
|
// src/utils/path.ts
|
|
5265
5851
|
function parseSqlitePath(path) {
|
|
5266
|
-
const emptyPath = `${
|
|
5852
|
+
const emptyPath = `${chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER}${chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER}`;
|
|
5267
5853
|
if (!path || path === emptyPath) return [];
|
|
5268
5854
|
const trimmed = path.slice(1, -1);
|
|
5269
5855
|
if (trimmed === "") return [];
|
|
5270
|
-
return trimmed.split(
|
|
5856
|
+
return trimmed.split(chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER);
|
|
5271
5857
|
}
|
|
5272
5858
|
function isSqlitePath(value) {
|
|
5273
|
-
return typeof value === "string" && value.startsWith(
|
|
5859
|
+
return typeof value === "string" && value.startsWith(chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER) && value.endsWith(chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER);
|
|
5274
5860
|
}
|
|
5275
5861
|
function normalizePath(value) {
|
|
5276
5862
|
if (Array.isArray(value)) {
|
|
@@ -5285,12 +5871,12 @@ function normalizePath(value) {
|
|
|
5285
5871
|
return [];
|
|
5286
5872
|
}
|
|
5287
5873
|
function isPostgresTextArray(value) {
|
|
5288
|
-
return typeof value === "string" && value.startsWith(
|
|
5874
|
+
return typeof value === "string" && value.startsWith(chunk3JK66E3I_cjs.PG_ARRAY_START) && value.endsWith(chunk3JK66E3I_cjs.PG_ARRAY_END);
|
|
5289
5875
|
}
|
|
5290
5876
|
function parsePostgresTextArray(value) {
|
|
5291
5877
|
const inner = value.slice(1, -1);
|
|
5292
5878
|
if (inner === "") return [];
|
|
5293
|
-
return inner.split(
|
|
5879
|
+
return inner.split(chunk3JK66E3I_cjs.PG_PATH_ELEMENT_SEPARATOR);
|
|
5294
5880
|
}
|
|
5295
5881
|
|
|
5296
5882
|
// src/query/execution/result-mapper.ts
|
|
@@ -5492,11 +6078,7 @@ function buildComparisonPredicate(field2, op, value) {
|
|
|
5492
6078
|
};
|
|
5493
6079
|
}
|
|
5494
6080
|
function buildCursorFromContext(context, orderBy, direction) {
|
|
5495
|
-
return buildCursorFromRow(
|
|
5496
|
-
context,
|
|
5497
|
-
orderBy,
|
|
5498
|
-
direction
|
|
5499
|
-
);
|
|
6081
|
+
return buildCursorFromRow(context, orderBy, direction);
|
|
5500
6082
|
}
|
|
5501
6083
|
function buildPaginatedResult(data, orderedRows, orderBy, limit, hasMore, isBackward, cursor, buildContext) {
|
|
5502
6084
|
let nextCursor;
|
|
@@ -5531,7 +6113,7 @@ async function* createStreamIterable(batchSize, paginate) {
|
|
|
5531
6113
|
}
|
|
5532
6114
|
}
|
|
5533
6115
|
function getStreamBatchSize(options) {
|
|
5534
|
-
return options?.batchSize ??
|
|
6116
|
+
return options?.batchSize ?? chunk3JK66E3I_cjs.DEFAULT_STREAM_BATCH_SIZE;
|
|
5535
6117
|
}
|
|
5536
6118
|
|
|
5537
6119
|
// src/query/execution/field-tracker.ts
|
|
@@ -5613,7 +6195,7 @@ function createNodeTrackingProxy(alias, kindNames, tracker, options) {
|
|
|
5613
6195
|
return getPlaceholderForSystemField(property, options.mode);
|
|
5614
6196
|
}
|
|
5615
6197
|
if (property === "meta") {
|
|
5616
|
-
for (const key of
|
|
6198
|
+
for (const key of chunk3JK66E3I_cjs.NODE_META_KEYS) {
|
|
5617
6199
|
tracker.record(alias, `meta.${key}`, true);
|
|
5618
6200
|
}
|
|
5619
6201
|
return buildNodeMetaPlaceholder(options.mode);
|
|
@@ -5646,7 +6228,7 @@ function createEdgeTrackingProxy(alias, edgeKindNames, tracker, options) {
|
|
|
5646
6228
|
return getPlaceholderForSystemField(property, options.mode);
|
|
5647
6229
|
}
|
|
5648
6230
|
if (property === "meta") {
|
|
5649
|
-
for (const key of
|
|
6231
|
+
for (const key of chunk3JK66E3I_cjs.EDGE_META_KEYS) {
|
|
5650
6232
|
tracker.record(alias, `meta.${key}`, true);
|
|
5651
6233
|
}
|
|
5652
6234
|
return buildEdgeMetaPlaceholder(options.mode);
|
|
@@ -6089,59 +6671,41 @@ function validateSqlIdentifier(alias) {
|
|
|
6089
6671
|
);
|
|
6090
6672
|
}
|
|
6091
6673
|
}
|
|
6092
|
-
function
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
{
|
|
6098
|
-
path,
|
|
6099
|
-
message: "Vector similarity predicates are only supported at top-level or inside AND groups."
|
|
6100
|
-
}
|
|
6101
|
-
]
|
|
6102
|
-
},
|
|
6103
|
-
{
|
|
6104
|
-
suggestion: "Rewrite the predicate to keep vector similarity at top-level or combine with additional filters using AND."
|
|
6105
|
-
}
|
|
6106
|
-
);
|
|
6107
|
-
}
|
|
6108
|
-
function validateVectorPredicateExpression(expression, inDisallowedBranch, path) {
|
|
6674
|
+
function validateStructuralPredicatePlacement(expression, matchType, buildError, inDisallowedBranch, path) {
|
|
6675
|
+
if (expression.__type === matchType) {
|
|
6676
|
+
if (inDisallowedBranch) buildError(path);
|
|
6677
|
+
return;
|
|
6678
|
+
}
|
|
6109
6679
|
switch (expression.__type) {
|
|
6110
|
-
case "vector_similarity": {
|
|
6111
|
-
if (inDisallowedBranch) {
|
|
6112
|
-
throwInvalidVectorPredicatePlacement(path);
|
|
6113
|
-
}
|
|
6114
|
-
return;
|
|
6115
|
-
}
|
|
6116
6680
|
case "and": {
|
|
6117
|
-
for (const [
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
predicate2,
|
|
6681
|
+
for (const [index, child] of expression.predicates.entries()) {
|
|
6682
|
+
validateStructuralPredicatePlacement(
|
|
6683
|
+
child,
|
|
6684
|
+
matchType,
|
|
6685
|
+
buildError,
|
|
6123
6686
|
inDisallowedBranch,
|
|
6124
|
-
`${path}.predicates[${
|
|
6687
|
+
`${path}.predicates[${index}]`
|
|
6125
6688
|
);
|
|
6126
6689
|
}
|
|
6127
6690
|
return;
|
|
6128
6691
|
}
|
|
6129
6692
|
case "or": {
|
|
6130
|
-
for (const [
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
predicate2,
|
|
6693
|
+
for (const [index, child] of expression.predicates.entries()) {
|
|
6694
|
+
validateStructuralPredicatePlacement(
|
|
6695
|
+
child,
|
|
6696
|
+
matchType,
|
|
6697
|
+
buildError,
|
|
6136
6698
|
true,
|
|
6137
|
-
`${path}.predicates[${
|
|
6699
|
+
`${path}.predicates[${index}]`
|
|
6138
6700
|
);
|
|
6139
6701
|
}
|
|
6140
6702
|
return;
|
|
6141
6703
|
}
|
|
6142
6704
|
case "not": {
|
|
6143
|
-
|
|
6705
|
+
validateStructuralPredicatePlacement(
|
|
6144
6706
|
expression.predicate,
|
|
6707
|
+
matchType,
|
|
6708
|
+
buildError,
|
|
6145
6709
|
true,
|
|
6146
6710
|
`${path}.predicate`
|
|
6147
6711
|
);
|
|
@@ -6155,24 +6719,108 @@ function validateVectorPredicateExpression(expression, inDisallowedBranch, path)
|
|
|
6155
6719
|
case "object_op":
|
|
6156
6720
|
case "aggregate_comparison":
|
|
6157
6721
|
case "exists":
|
|
6158
|
-
case "in_subquery":
|
|
6722
|
+
case "in_subquery":
|
|
6723
|
+
case "vector_similarity":
|
|
6724
|
+
case "fulltext_match": {
|
|
6159
6725
|
return;
|
|
6160
6726
|
}
|
|
6161
6727
|
}
|
|
6162
6728
|
}
|
|
6729
|
+
function throwInvalidVectorPredicatePlacement(path) {
|
|
6730
|
+
throw new chunkO5PST6TB_cjs.ValidationError(
|
|
6731
|
+
"Vector similarity predicates cannot be nested under OR or NOT. Use top-level AND combinations instead.",
|
|
6732
|
+
{
|
|
6733
|
+
issues: [
|
|
6734
|
+
{
|
|
6735
|
+
path,
|
|
6736
|
+
message: "Vector similarity predicates are only supported at top-level or inside AND groups."
|
|
6737
|
+
}
|
|
6738
|
+
]
|
|
6739
|
+
},
|
|
6740
|
+
{
|
|
6741
|
+
suggestion: "Rewrite the predicate to keep vector similarity at top-level or combine with additional filters using AND."
|
|
6742
|
+
}
|
|
6743
|
+
);
|
|
6744
|
+
}
|
|
6745
|
+
function throwInvalidFulltextPredicatePlacement(path) {
|
|
6746
|
+
throw new chunkO5PST6TB_cjs.ValidationError(
|
|
6747
|
+
"Fulltext match predicates (.matches()) cannot be nested under OR or NOT. Use top-level AND combinations instead.",
|
|
6748
|
+
{
|
|
6749
|
+
issues: [
|
|
6750
|
+
{
|
|
6751
|
+
path,
|
|
6752
|
+
message: "Fulltext match predicates are only supported at top-level or inside AND groups."
|
|
6753
|
+
}
|
|
6754
|
+
]
|
|
6755
|
+
},
|
|
6756
|
+
{
|
|
6757
|
+
suggestion: "Restructure your query so the fulltext match appears at the top level of a whereNode() or inside an .and() combination."
|
|
6758
|
+
}
|
|
6759
|
+
);
|
|
6760
|
+
}
|
|
6163
6761
|
function validateVectorPredicatePlacement(predicates) {
|
|
6164
|
-
for (const [
|
|
6165
|
-
|
|
6762
|
+
for (const [index, predicate2] of predicates.entries()) {
|
|
6763
|
+
validateStructuralPredicatePlacement(
|
|
6764
|
+
predicate2.expression,
|
|
6765
|
+
"vector_similarity",
|
|
6766
|
+
throwInvalidVectorPredicatePlacement,
|
|
6767
|
+
false,
|
|
6768
|
+
`predicates[${index}].expression`
|
|
6769
|
+
);
|
|
6770
|
+
}
|
|
6771
|
+
}
|
|
6772
|
+
function validateFulltextPredicatePlacement(predicates) {
|
|
6773
|
+
for (const [index, predicate2] of predicates.entries()) {
|
|
6774
|
+
validateStructuralPredicatePlacement(
|
|
6166
6775
|
predicate2.expression,
|
|
6776
|
+
"fulltext_match",
|
|
6777
|
+
throwInvalidFulltextPredicatePlacement,
|
|
6167
6778
|
false,
|
|
6168
|
-
`predicates[${
|
|
6779
|
+
`predicates[${index}].expression`
|
|
6780
|
+
);
|
|
6781
|
+
}
|
|
6782
|
+
}
|
|
6783
|
+
function validateHybridFusionOptions(options) {
|
|
6784
|
+
const method = options.method;
|
|
6785
|
+
if (method !== void 0 && method !== "rrf") {
|
|
6786
|
+
throw new chunkO5PST6TB_cjs.ValidationError(`Unsupported fusion method: ${method}`, {
|
|
6787
|
+
issues: [{ path: "fusion.method", message: `Only "rrf" is supported.` }]
|
|
6788
|
+
});
|
|
6789
|
+
}
|
|
6790
|
+
const { k } = options;
|
|
6791
|
+
if (k !== void 0 && (!Number.isFinite(k) || k <= 0)) {
|
|
6792
|
+
throw new chunkO5PST6TB_cjs.ValidationError(
|
|
6793
|
+
`Fusion k must be a positive finite number, got: ${String(k)}`,
|
|
6794
|
+
{
|
|
6795
|
+
issues: [{ path: "fusion.k", message: "Must be a positive number." }]
|
|
6796
|
+
}
|
|
6169
6797
|
);
|
|
6170
6798
|
}
|
|
6799
|
+
const weights = options.weights;
|
|
6800
|
+
if (weights !== void 0) {
|
|
6801
|
+
for (const key of ["vector", "fulltext"]) {
|
|
6802
|
+
const weight = weights[key];
|
|
6803
|
+
if (weight !== void 0 && (!Number.isFinite(weight) || weight < 0)) {
|
|
6804
|
+
throw new chunkO5PST6TB_cjs.ValidationError(
|
|
6805
|
+
`Fusion weight for "${key}" must be a non-negative finite number, got: ${String(weight)}`,
|
|
6806
|
+
{
|
|
6807
|
+
issues: [
|
|
6808
|
+
{
|
|
6809
|
+
path: `fusion.weights.${key}`,
|
|
6810
|
+
message: "Must be a non-negative number."
|
|
6811
|
+
}
|
|
6812
|
+
]
|
|
6813
|
+
}
|
|
6814
|
+
);
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6171
6818
|
}
|
|
6172
6819
|
|
|
6173
6820
|
// src/query/builder/ast-builder.ts
|
|
6174
6821
|
function buildQueryAst(config, state) {
|
|
6175
6822
|
validateVectorPredicatePlacement(state.predicates);
|
|
6823
|
+
validateFulltextPredicatePlacement(state.predicates);
|
|
6176
6824
|
const temporalMode = {
|
|
6177
6825
|
mode: state.temporalMode
|
|
6178
6826
|
};
|
|
@@ -6196,7 +6844,18 @@ function buildQueryAst(config, state) {
|
|
|
6196
6844
|
...state.limit !== void 0 && { limit: state.limit },
|
|
6197
6845
|
...state.offset !== void 0 && { offset: state.offset },
|
|
6198
6846
|
...state.groupBy !== void 0 && { groupBy: state.groupBy },
|
|
6199
|
-
...state.having !== void 0 && { having: state.having }
|
|
6847
|
+
...state.having !== void 0 && { having: state.having },
|
|
6848
|
+
...state.fusion !== void 0 && { fusion: state.fusion }
|
|
6849
|
+
};
|
|
6850
|
+
}
|
|
6851
|
+
|
|
6852
|
+
// src/query/builder/compile-options.ts
|
|
6853
|
+
function buildCompileOptions(config) {
|
|
6854
|
+
const fulltextStrategy = config.backend?.fulltextStrategy;
|
|
6855
|
+
return {
|
|
6856
|
+
dialect: config.dialect ?? "sqlite",
|
|
6857
|
+
schema: config.schema,
|
|
6858
|
+
...fulltextStrategy === void 0 ? {} : { fulltextStrategy }
|
|
6200
6859
|
};
|
|
6201
6860
|
}
|
|
6202
6861
|
function toLiteral(value) {
|
|
@@ -6298,7 +6957,8 @@ function substitutePredicateExpression(expr, bindings) {
|
|
|
6298
6957
|
case "array_op":
|
|
6299
6958
|
case "object_op":
|
|
6300
6959
|
case "aggregate_comparison":
|
|
6301
|
-
case "vector_similarity":
|
|
6960
|
+
case "vector_similarity":
|
|
6961
|
+
case "fulltext_match": {
|
|
6302
6962
|
return expr;
|
|
6303
6963
|
}
|
|
6304
6964
|
case "exists": {
|
|
@@ -6337,7 +6997,7 @@ function substituteParameters(ast, bindings) {
|
|
|
6337
6997
|
};
|
|
6338
6998
|
}
|
|
6339
6999
|
function fillPlaceholders(params, bindings, dialect) {
|
|
6340
|
-
const adapter =
|
|
7000
|
+
const adapter = chunk3JK66E3I_cjs.getDialect(dialect);
|
|
6341
7001
|
return params.map((parameter) => {
|
|
6342
7002
|
if (parameter instanceof drizzleOrm.Placeholder) {
|
|
6343
7003
|
const name = parameter.name;
|
|
@@ -6550,7 +7210,8 @@ function collectParameterMetadataFromExpression(expression, names, stringOpParam
|
|
|
6550
7210
|
case "array_op":
|
|
6551
7211
|
case "object_op":
|
|
6552
7212
|
case "aggregate_comparison":
|
|
6553
|
-
case "vector_similarity":
|
|
7213
|
+
case "vector_similarity":
|
|
7214
|
+
case "fulltext_match": {
|
|
6554
7215
|
return;
|
|
6555
7216
|
}
|
|
6556
7217
|
case "exists": {
|
|
@@ -6681,7 +7342,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6681
7342
|
direction
|
|
6682
7343
|
} : {
|
|
6683
7344
|
field: fieldRef(alias, ["props"], {
|
|
6684
|
-
jsonPointer:
|
|
7345
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
6685
7346
|
valueType: typeInfo?.valueType,
|
|
6686
7347
|
elementType: typeInfo?.elementType
|
|
6687
7348
|
}),
|
|
@@ -6905,10 +7566,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6905
7566
|
* Builds compile options from the config.
|
|
6906
7567
|
*/
|
|
6907
7568
|
#compileOptions() {
|
|
6908
|
-
return
|
|
6909
|
-
dialect: this.#config.dialect ?? "sqlite",
|
|
6910
|
-
schema: this.#config.schema
|
|
6911
|
-
};
|
|
7569
|
+
return buildCompileOptions(this.#config);
|
|
6912
7570
|
}
|
|
6913
7571
|
#requireBackend() {
|
|
6914
7572
|
const { backend } = this.#config;
|
|
@@ -7290,7 +7948,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7290
7948
|
if (field2.jsonPointer === void 0) {
|
|
7291
7949
|
return false;
|
|
7292
7950
|
}
|
|
7293
|
-
const segments =
|
|
7951
|
+
const segments = chunkUVZHTBZ5_cjs.parseJsonPointer(field2.jsonPointer);
|
|
7294
7952
|
if (segments.length !== 1) {
|
|
7295
7953
|
return false;
|
|
7296
7954
|
}
|
|
@@ -7338,7 +7996,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7338
7996
|
aliasObject2[fieldName] = nullToUndefined(row[outputName2]);
|
|
7339
7997
|
continue;
|
|
7340
7998
|
}
|
|
7341
|
-
const segments =
|
|
7999
|
+
const segments = chunkUVZHTBZ5_cjs.parseJsonPointer(jsonPointer2);
|
|
7342
8000
|
if (segments.length === 0) {
|
|
7343
8001
|
throw new MissingSelectiveFieldError(alias, "orderBy");
|
|
7344
8002
|
}
|
|
@@ -7434,7 +8092,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7434
8092
|
);
|
|
7435
8093
|
}
|
|
7436
8094
|
const isBackward = options.last !== void 0 || options.before !== void 0;
|
|
7437
|
-
const limit = options.first ?? options.last ??
|
|
8095
|
+
const limit = options.first ?? options.last ?? chunk3JK66E3I_cjs.DEFAULT_PAGINATION_LIMIT;
|
|
7438
8096
|
const cursor = options.after ?? options.before;
|
|
7439
8097
|
let cursorData;
|
|
7440
8098
|
if (cursor) {
|
|
@@ -7623,14 +8281,8 @@ var ExecutableAggregateQuery = class _ExecutableAggregateQuery {
|
|
|
7623
8281
|
this.#cachedCompiled = compiled;
|
|
7624
8282
|
return compiled;
|
|
7625
8283
|
}
|
|
7626
|
-
/**
|
|
7627
|
-
* Builds compile options from the config.
|
|
7628
|
-
*/
|
|
7629
8284
|
#compileOptions() {
|
|
7630
|
-
return
|
|
7631
|
-
dialect: this.#config.dialect ?? "sqlite",
|
|
7632
|
-
schema: this.#config.schema
|
|
7633
|
-
};
|
|
8285
|
+
return buildCompileOptions(this.#config);
|
|
7634
8286
|
}
|
|
7635
8287
|
/**
|
|
7636
8288
|
* Executes the query and returns typed results.
|
|
@@ -7861,7 +8513,7 @@ var TraversalBuilder = class _TraversalBuilder {
|
|
|
7861
8513
|
const valueType = typeInfo?.valueType;
|
|
7862
8514
|
const elementType = typeInfo?.elementType;
|
|
7863
8515
|
const ref = fieldRef(alias, ["props"], {
|
|
7864
|
-
jsonPointer:
|
|
8516
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([propertyName]),
|
|
7865
8517
|
valueType,
|
|
7866
8518
|
elementType
|
|
7867
8519
|
});
|
|
@@ -8181,7 +8833,7 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8181
8833
|
if (source.valueType !== void 0 || source.path.length !== 1 || source.path[0] !== "props" || source.jsonPointer === void 0) {
|
|
8182
8834
|
return [outputName, source];
|
|
8183
8835
|
}
|
|
8184
|
-
const segments =
|
|
8836
|
+
const segments = chunkUVZHTBZ5_cjs.parseJsonPointer(source.jsonPointer);
|
|
8185
8837
|
if (segments.length !== 1) {
|
|
8186
8838
|
return [outputName, source];
|
|
8187
8839
|
}
|
|
@@ -8235,7 +8887,7 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8235
8887
|
direction
|
|
8236
8888
|
} : {
|
|
8237
8889
|
field: fieldRef(alias, ["props"], {
|
|
8238
|
-
jsonPointer:
|
|
8890
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
8239
8891
|
valueType: typeInfo?.valueType,
|
|
8240
8892
|
elementType: typeInfo?.elementType
|
|
8241
8893
|
}),
|
|
@@ -8310,7 +8962,7 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8310
8962
|
__type: "field_ref",
|
|
8311
8963
|
alias,
|
|
8312
8964
|
path: ["props"],
|
|
8313
|
-
jsonPointer:
|
|
8965
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
8314
8966
|
valueType: typeInfo?.valueType,
|
|
8315
8967
|
elementType: typeInfo?.elementType
|
|
8316
8968
|
};
|
|
@@ -8357,6 +9009,36 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8357
9009
|
having: predicate2
|
|
8358
9010
|
});
|
|
8359
9011
|
}
|
|
9012
|
+
/**
|
|
9013
|
+
* Sets fusion parameters for hybrid (vector + fulltext) queries.
|
|
9014
|
+
*
|
|
9015
|
+
* Applies only when the query contains both a `.similarTo()` and a
|
|
9016
|
+
* `.$fulltext.matches()` predicate. Without this call, the default is
|
|
9017
|
+
* RRF with k=60 and equal weights. A mismatch between `.fuseWith()`
|
|
9018
|
+
* configuration and the predicates on the query is caught during
|
|
9019
|
+
* compilation, not here.
|
|
9020
|
+
*
|
|
9021
|
+
* @example
|
|
9022
|
+
* ```typescript
|
|
9023
|
+
* store.query()
|
|
9024
|
+
* .from("Document", "d")
|
|
9025
|
+
* .whereNode("d", d =>
|
|
9026
|
+
* d.$fulltext.matches("renewable energy", 50)
|
|
9027
|
+
* .and(d.embedding.similarTo(vec, 50))
|
|
9028
|
+
* .and(d.tenantId.eq(tenant))
|
|
9029
|
+
* )
|
|
9030
|
+
* .fuseWith({ k: 60, weights: { fulltext: 1.5 } })
|
|
9031
|
+
* .limit(10)
|
|
9032
|
+
* .execute();
|
|
9033
|
+
* ```
|
|
9034
|
+
*/
|
|
9035
|
+
fuseWith(options) {
|
|
9036
|
+
validateHybridFusionOptions(options);
|
|
9037
|
+
return new _QueryBuilder(this.#config, {
|
|
9038
|
+
...this.#state,
|
|
9039
|
+
fusion: options
|
|
9040
|
+
});
|
|
9041
|
+
}
|
|
8360
9042
|
/**
|
|
8361
9043
|
* Applies a query fragment to transform this builder.
|
|
8362
9044
|
*
|
|
@@ -8408,42 +9090,14 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8408
9090
|
property
|
|
8409
9091
|
) : void 0;
|
|
8410
9092
|
const ref = fieldRef(alias, ["props"], {
|
|
8411
|
-
jsonPointer:
|
|
9093
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([property]),
|
|
8412
9094
|
valueType: typeInfo?.valueType,
|
|
8413
9095
|
elementType: typeInfo?.elementType
|
|
8414
9096
|
});
|
|
8415
9097
|
return this.#buildFieldBuilderForTypeInfo(ref, typeInfo);
|
|
8416
9098
|
}
|
|
8417
9099
|
#buildFieldBuilderForTypeInfo(ref, typeInfo) {
|
|
8418
|
-
|
|
8419
|
-
return baseField(ref);
|
|
8420
|
-
}
|
|
8421
|
-
switch (typeInfo.valueType) {
|
|
8422
|
-
case "string": {
|
|
8423
|
-
return stringField(ref);
|
|
8424
|
-
}
|
|
8425
|
-
case "number": {
|
|
8426
|
-
return numberField(ref);
|
|
8427
|
-
}
|
|
8428
|
-
case "boolean": {
|
|
8429
|
-
return baseField(ref);
|
|
8430
|
-
}
|
|
8431
|
-
case "date": {
|
|
8432
|
-
return dateField(ref);
|
|
8433
|
-
}
|
|
8434
|
-
case "array": {
|
|
8435
|
-
return arrayField(ref);
|
|
8436
|
-
}
|
|
8437
|
-
case "object": {
|
|
8438
|
-
return objectField(ref, { typeInfo });
|
|
8439
|
-
}
|
|
8440
|
-
case "embedding": {
|
|
8441
|
-
return embeddingField(ref);
|
|
8442
|
-
}
|
|
8443
|
-
case "unknown": {
|
|
8444
|
-
return baseField(ref);
|
|
8445
|
-
}
|
|
8446
|
-
}
|
|
9100
|
+
return buildFieldBuilderForTypeInfo(ref, typeInfo);
|
|
8447
9101
|
}
|
|
8448
9102
|
#createNodeAccessor(alias) {
|
|
8449
9103
|
const kindNames = this.#getKindNamesForAlias(alias);
|
|
@@ -8453,6 +9107,10 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8453
9107
|
const kindAccessor = stringField(
|
|
8454
9108
|
fieldRef(alias, ["kind"], { valueType: "string" })
|
|
8455
9109
|
);
|
|
9110
|
+
const fulltextAccessor = createFulltextAccessor(
|
|
9111
|
+
alias,
|
|
9112
|
+
() => this.#hasSearchableField(kindNames)
|
|
9113
|
+
);
|
|
8456
9114
|
return new Proxy({}, {
|
|
8457
9115
|
get: (_, property) => {
|
|
8458
9116
|
if (typeof property === "symbol") return;
|
|
@@ -8460,10 +9118,15 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8460
9118
|
if (property === "toJSON") return;
|
|
8461
9119
|
if (property === "id") return idAccessor;
|
|
8462
9120
|
if (property === "kind") return kindAccessor;
|
|
9121
|
+
if (property === "$fulltext") return fulltextAccessor;
|
|
8463
9122
|
return this.#getFieldBuilderForProperty(kindNames, property, alias);
|
|
8464
9123
|
}
|
|
8465
9124
|
});
|
|
8466
9125
|
}
|
|
9126
|
+
#hasSearchableField(kindNames) {
|
|
9127
|
+
if (!kindNames) return false;
|
|
9128
|
+
return this.#config.schemaIntrospector.hasSearchableField(kindNames);
|
|
9129
|
+
}
|
|
8467
9130
|
#expandTraversalEdgeKinds(edgeKind, includeImplyingEdges) {
|
|
8468
9131
|
return includeImplyingEdges ? this.#config.registry.expandImplyingEdges(edgeKind) : [edgeKind];
|
|
8469
9132
|
}
|
|
@@ -8506,7 +9169,7 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
8506
9169
|
property
|
|
8507
9170
|
) : void 0;
|
|
8508
9171
|
const ref = fieldRef(alias, ["props"], {
|
|
8509
|
-
jsonPointer:
|
|
9172
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([property]),
|
|
8510
9173
|
valueType: typeInfo?.valueType,
|
|
8511
9174
|
elementType: typeInfo?.elementType
|
|
8512
9175
|
});
|
|
@@ -8689,14 +9352,8 @@ var UnionableQuery = class _UnionableQuery {
|
|
|
8689
9352
|
this.#cachedCompiled = compiled;
|
|
8690
9353
|
return compiled;
|
|
8691
9354
|
}
|
|
8692
|
-
/**
|
|
8693
|
-
* Builds compile options from the config.
|
|
8694
|
-
*/
|
|
8695
9355
|
#compileOptions() {
|
|
8696
|
-
return
|
|
8697
|
-
dialect: this.#config.dialect ?? "sqlite",
|
|
8698
|
-
schema: this.#config.schema
|
|
8699
|
-
};
|
|
9356
|
+
return buildCompileOptions(this.#config);
|
|
8700
9357
|
}
|
|
8701
9358
|
/**
|
|
8702
9359
|
* Executes the combined query.
|
|
@@ -8758,7 +9415,7 @@ function count(alias, field2) {
|
|
|
8758
9415
|
__type: "field_ref",
|
|
8759
9416
|
alias,
|
|
8760
9417
|
path: field2 ? ["props"] : ["id"],
|
|
8761
|
-
jsonPointer: field2 ?
|
|
9418
|
+
jsonPointer: field2 ? chunkUVZHTBZ5_cjs.jsonPointer([field2]) : void 0,
|
|
8762
9419
|
valueType: field2 ? void 0 : "string"
|
|
8763
9420
|
}
|
|
8764
9421
|
};
|
|
@@ -8771,11 +9428,17 @@ function countDistinct(alias, field2) {
|
|
|
8771
9428
|
__type: "field_ref",
|
|
8772
9429
|
alias,
|
|
8773
9430
|
path: field2 ? ["props"] : ["id"],
|
|
8774
|
-
jsonPointer: field2 ?
|
|
9431
|
+
jsonPointer: field2 ? chunkUVZHTBZ5_cjs.jsonPointer([field2]) : void 0,
|
|
8775
9432
|
valueType: field2 ? void 0 : "string"
|
|
8776
9433
|
}
|
|
8777
9434
|
};
|
|
8778
9435
|
}
|
|
9436
|
+
function countEdges(edgeAlias) {
|
|
9437
|
+
return count(edgeAlias);
|
|
9438
|
+
}
|
|
9439
|
+
function countDistinctEdges(edgeAlias) {
|
|
9440
|
+
return countDistinct(edgeAlias);
|
|
9441
|
+
}
|
|
8779
9442
|
function sum(alias, field2) {
|
|
8780
9443
|
return {
|
|
8781
9444
|
__type: "aggregate",
|
|
@@ -8784,7 +9447,7 @@ function sum(alias, field2) {
|
|
|
8784
9447
|
__type: "field_ref",
|
|
8785
9448
|
alias,
|
|
8786
9449
|
path: ["props"],
|
|
8787
|
-
jsonPointer:
|
|
9450
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
8788
9451
|
valueType: "number"
|
|
8789
9452
|
}
|
|
8790
9453
|
};
|
|
@@ -8797,7 +9460,7 @@ function avg(alias, field2) {
|
|
|
8797
9460
|
__type: "field_ref",
|
|
8798
9461
|
alias,
|
|
8799
9462
|
path: ["props"],
|
|
8800
|
-
jsonPointer:
|
|
9463
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
8801
9464
|
valueType: "number"
|
|
8802
9465
|
}
|
|
8803
9466
|
};
|
|
@@ -8810,7 +9473,7 @@ function min(alias, field2) {
|
|
|
8810
9473
|
__type: "field_ref",
|
|
8811
9474
|
alias,
|
|
8812
9475
|
path: ["props"],
|
|
8813
|
-
jsonPointer:
|
|
9476
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
8814
9477
|
valueType: "number"
|
|
8815
9478
|
}
|
|
8816
9479
|
};
|
|
@@ -8823,7 +9486,7 @@ function max(alias, field2) {
|
|
|
8823
9486
|
__type: "field_ref",
|
|
8824
9487
|
alias,
|
|
8825
9488
|
path: ["props"],
|
|
8826
|
-
jsonPointer:
|
|
9489
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer([field2]),
|
|
8827
9490
|
valueType: "number"
|
|
8828
9491
|
}
|
|
8829
9492
|
};
|
|
@@ -8854,7 +9517,7 @@ function field(alias, ...path) {
|
|
|
8854
9517
|
__type: "field_ref",
|
|
8855
9518
|
alias,
|
|
8856
9519
|
path: ["props"],
|
|
8857
|
-
jsonPointer:
|
|
9520
|
+
jsonPointer: chunkUVZHTBZ5_cjs.jsonPointer(path)
|
|
8858
9521
|
};
|
|
8859
9522
|
}
|
|
8860
9523
|
function having(aggregate, op, value) {
|
|
@@ -8912,16 +9575,12 @@ function offsetFragment(n) {
|
|
|
8912
9575
|
}
|
|
8913
9576
|
|
|
8914
9577
|
// src/query/builder/index.ts
|
|
8915
|
-
setQueryBuilderClass(
|
|
8916
|
-
|
|
8917
|
-
);
|
|
8918
|
-
setUnionableQueryClass(
|
|
8919
|
-
UnionableQuery
|
|
8920
|
-
);
|
|
9578
|
+
setQueryBuilderClass(QueryBuilder);
|
|
9579
|
+
setUnionableQueryClass(UnionableQuery);
|
|
8921
9580
|
|
|
8922
9581
|
// src/query/builder.ts
|
|
8923
9582
|
function createQueryBuilder(graphId, registry, options) {
|
|
8924
|
-
const schemaIntrospector =
|
|
9583
|
+
const schemaIntrospector = chunkUVZHTBZ5_cjs.createSchemaIntrospector(
|
|
8925
9584
|
registry.nodeKinds,
|
|
8926
9585
|
registry.edgeKinds
|
|
8927
9586
|
);
|
|
@@ -8948,7 +9607,8 @@ function createQueryBuilder(graphId, registry, options) {
|
|
|
8948
9607
|
temporalMode: "current",
|
|
8949
9608
|
asOf: void 0,
|
|
8950
9609
|
groupBy: void 0,
|
|
8951
|
-
having: void 0
|
|
9610
|
+
having: void 0,
|
|
9611
|
+
fusion: void 0
|
|
8952
9612
|
};
|
|
8953
9613
|
return new QueryBuilder(config, initialState);
|
|
8954
9614
|
}
|
|
@@ -8957,12 +9617,12 @@ function createQueryBuilder(graphId, registry, options) {
|
|
|
8957
9617
|
function buildKindRegistry(graph) {
|
|
8958
9618
|
const nodeTypes = extractNodeTypes(graph);
|
|
8959
9619
|
const edgeTypes = extractEdgeTypes(graph);
|
|
8960
|
-
const closures = graph.ontology.length > 0 ?
|
|
8961
|
-
return new
|
|
9620
|
+
const closures = graph.ontology.length > 0 ? chunkHRNQ3DVJ_cjs.computeClosuresFromOntology(graph.ontology) : chunkHRNQ3DVJ_cjs.createEmptyClosures();
|
|
9621
|
+
return new chunkHRNQ3DVJ_cjs.KindRegistry(nodeTypes, edgeTypes, closures);
|
|
8962
9622
|
}
|
|
8963
9623
|
function extractNodeTypes(graph) {
|
|
8964
9624
|
const result = /* @__PURE__ */ new Map();
|
|
8965
|
-
for (const typeName of
|
|
9625
|
+
for (const typeName of chunkWRWVWKQL_cjs.getNodeKinds(graph)) {
|
|
8966
9626
|
const registration = graph.nodes[typeName];
|
|
8967
9627
|
result.set(typeName, registration.type);
|
|
8968
9628
|
}
|
|
@@ -8970,7 +9630,7 @@ function extractNodeTypes(graph) {
|
|
|
8970
9630
|
}
|
|
8971
9631
|
function extractEdgeTypes(graph) {
|
|
8972
9632
|
const result = /* @__PURE__ */ new Map();
|
|
8973
|
-
for (const typeName of
|
|
9633
|
+
for (const typeName of chunkWRWVWKQL_cjs.getEdgeKinds(graph)) {
|
|
8974
9634
|
const registration = graph.edges[typeName];
|
|
8975
9635
|
result.set(typeName, registration.type);
|
|
8976
9636
|
}
|
|
@@ -9184,7 +9844,7 @@ function createGraphAlgorithms(params) {
|
|
|
9184
9844
|
const ctx = {
|
|
9185
9845
|
graphId: params.graphId,
|
|
9186
9846
|
backend: params.backend,
|
|
9187
|
-
dialect:
|
|
9847
|
+
dialect: chunk3JK66E3I_cjs.getDialect(params.backend.dialect),
|
|
9188
9848
|
schema: params.schema ?? (params.backend.tableNames ? createSqlSchema(params.backend.tableNames) : createSqlSchema()),
|
|
9189
9849
|
defaultTemporalMode: params.defaultTemporalMode
|
|
9190
9850
|
};
|
|
@@ -9289,20 +9949,13 @@ function createEdgeCollection(config) {
|
|
|
9289
9949
|
const result = {};
|
|
9290
9950
|
if (options?.matchOn !== void 0)
|
|
9291
9951
|
result.matchOn = options.matchOn;
|
|
9292
|
-
if (options?.props !== void 0)
|
|
9293
|
-
result.props = options.props;
|
|
9952
|
+
if (options?.props !== void 0) result.props = options.props;
|
|
9294
9953
|
return result;
|
|
9295
9954
|
}
|
|
9296
9955
|
return {
|
|
9297
9956
|
async create(from, to, props, options) {
|
|
9298
9957
|
const result = await executeEdgeCreate2(
|
|
9299
|
-
buildCreateEdgeInput(
|
|
9300
|
-
kind,
|
|
9301
|
-
from,
|
|
9302
|
-
to,
|
|
9303
|
-
props ?? {},
|
|
9304
|
-
options
|
|
9305
|
-
),
|
|
9958
|
+
buildCreateEdgeInput(kind, from, to, props ?? {}, options),
|
|
9306
9959
|
backend
|
|
9307
9960
|
);
|
|
9308
9961
|
return narrowEdge(result);
|
|
@@ -9397,7 +10050,7 @@ function createEdgeCollection(config) {
|
|
|
9397
10050
|
temporalMode: mode
|
|
9398
10051
|
};
|
|
9399
10052
|
if (mode === "current" || mode === "asOf") {
|
|
9400
|
-
params.asOf = options?.asOf ??
|
|
10053
|
+
params.asOf = options?.asOf ?? chunkWRWVWKQL_cjs.nowIso();
|
|
9401
10054
|
}
|
|
9402
10055
|
if (options?.from?.kind !== void 0)
|
|
9403
10056
|
params.fromKind = options.from.kind;
|
|
@@ -9418,7 +10071,7 @@ function createEdgeCollection(config) {
|
|
|
9418
10071
|
temporalMode: mode
|
|
9419
10072
|
};
|
|
9420
10073
|
if (mode === "current" || mode === "asOf") {
|
|
9421
|
-
params.asOf = options?.asOf ??
|
|
10074
|
+
params.asOf = options?.asOf ?? chunkWRWVWKQL_cjs.nowIso();
|
|
9422
10075
|
}
|
|
9423
10076
|
if (options?.from?.kind !== void 0)
|
|
9424
10077
|
params.fromKind = options.from.kind;
|
|
@@ -9428,10 +10081,7 @@ function createEdgeCollection(config) {
|
|
|
9428
10081
|
return backend.countEdgesByKind(params);
|
|
9429
10082
|
},
|
|
9430
10083
|
async bulkCreate(items) {
|
|
9431
|
-
const batchInputs = mapBulkEdgeInputs(
|
|
9432
|
-
kind,
|
|
9433
|
-
items
|
|
9434
|
-
);
|
|
10084
|
+
const batchInputs = mapBulkEdgeInputs(kind, items);
|
|
9435
10085
|
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
9436
10086
|
const results2 = await backend.transaction(
|
|
9437
10087
|
async (txBackend) => executeEdgeCreateBatch2(batchInputs, txBackend)
|
|
@@ -9467,11 +10117,7 @@ function createEdgeCollection(config) {
|
|
|
9467
10117
|
if (existing) {
|
|
9468
10118
|
toUpdate.push({
|
|
9469
10119
|
index: itemIndex,
|
|
9470
|
-
input: buildUpdateEdgeInput(
|
|
9471
|
-
item.id,
|
|
9472
|
-
item.props ?? {},
|
|
9473
|
-
item
|
|
9474
|
-
),
|
|
10120
|
+
input: buildUpdateEdgeInput(item.id, item.props ?? {}, item),
|
|
9475
10121
|
clearDeleted: existing.deleted_at !== void 0
|
|
9476
10122
|
});
|
|
9477
10123
|
} else {
|
|
@@ -9510,10 +10156,7 @@ function createEdgeCollection(config) {
|
|
|
9510
10156
|
return upsertAll(backend);
|
|
9511
10157
|
},
|
|
9512
10158
|
async bulkInsert(items) {
|
|
9513
|
-
const batchInputs = mapBulkEdgeInputs(
|
|
9514
|
-
kind,
|
|
9515
|
-
items
|
|
9516
|
-
);
|
|
10159
|
+
const batchInputs = mapBulkEdgeInputs(kind, items);
|
|
9517
10160
|
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
9518
10161
|
await backend.transaction(async (txBackend) => {
|
|
9519
10162
|
await executeEdgeCreateNoReturnBatch2(batchInputs, txBackend);
|
|
@@ -9664,11 +10307,7 @@ function createNodeCollection(config) {
|
|
|
9664
10307
|
async getByIds(ids, options) {
|
|
9665
10308
|
if (ids.length === 0) return [];
|
|
9666
10309
|
if (backend.getNodes !== void 0) {
|
|
9667
|
-
const rows = await backend.getNodes(
|
|
9668
|
-
graphId,
|
|
9669
|
-
kind,
|
|
9670
|
-
ids
|
|
9671
|
-
);
|
|
10310
|
+
const rows = await backend.getNodes(graphId, kind, ids);
|
|
9672
10311
|
const rowMap = /* @__PURE__ */ new Map();
|
|
9673
10312
|
for (const row of rows) {
|
|
9674
10313
|
rowMap.set(row.id, row);
|
|
@@ -9713,7 +10352,7 @@ function createNodeCollection(config) {
|
|
|
9713
10352
|
const mode2 = options.temporalMode ?? defaultTemporalMode;
|
|
9714
10353
|
let query = createQuery().from(kind, "_n").temporal(
|
|
9715
10354
|
mode2,
|
|
9716
|
-
mode2 === "asOf" ? options.asOf ??
|
|
10355
|
+
mode2 === "asOf" ? options.asOf ?? chunkWRWVWKQL_cjs.nowIso() : void 0
|
|
9717
10356
|
).whereNode("_n", options.where).select((ctx) => ctx._n);
|
|
9718
10357
|
if (options.limit !== void 0) query = query.limit(options.limit);
|
|
9719
10358
|
if (options.offset !== void 0) query = query.offset(options.offset);
|
|
@@ -9728,7 +10367,7 @@ function createNodeCollection(config) {
|
|
|
9728
10367
|
temporalMode: mode
|
|
9729
10368
|
};
|
|
9730
10369
|
if (mode === "current" || mode === "asOf") {
|
|
9731
|
-
params.asOf = options?.asOf ??
|
|
10370
|
+
params.asOf = options?.asOf ?? chunkWRWVWKQL_cjs.nowIso();
|
|
9732
10371
|
}
|
|
9733
10372
|
if (options?.limit !== void 0) params.limit = options.limit;
|
|
9734
10373
|
if (options?.offset !== void 0) params.offset = options.offset;
|
|
@@ -9744,16 +10383,12 @@ function createNodeCollection(config) {
|
|
|
9744
10383
|
temporalMode: mode
|
|
9745
10384
|
};
|
|
9746
10385
|
if (mode === "current" || mode === "asOf") {
|
|
9747
|
-
params.asOf = options?.asOf ??
|
|
10386
|
+
params.asOf = options?.asOf ?? chunkWRWVWKQL_cjs.nowIso();
|
|
9748
10387
|
}
|
|
9749
10388
|
return backend.countNodesByKind(params);
|
|
9750
10389
|
},
|
|
9751
10390
|
async upsertById(id, props, options) {
|
|
9752
|
-
return this.upsertByIdFromRecord(
|
|
9753
|
-
id,
|
|
9754
|
-
props,
|
|
9755
|
-
options
|
|
9756
|
-
);
|
|
10391
|
+
return this.upsertByIdFromRecord(id, props, options);
|
|
9757
10392
|
},
|
|
9758
10393
|
async upsertByIdFromRecord(id, data, options) {
|
|
9759
10394
|
const existing = await backend.getNode(graphId, kind, id);
|
|
@@ -9773,10 +10408,7 @@ function createNodeCollection(config) {
|
|
|
9773
10408
|
return narrowNode(result);
|
|
9774
10409
|
},
|
|
9775
10410
|
async bulkCreate(items) {
|
|
9776
|
-
const batchInputs = mapBulkNodeInputs(
|
|
9777
|
-
kind,
|
|
9778
|
-
items
|
|
9779
|
-
);
|
|
10411
|
+
const batchInputs = mapBulkNodeInputs(kind, items);
|
|
9780
10412
|
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
9781
10413
|
const results2 = await backend.transaction(
|
|
9782
10414
|
async (txBackend) => executeNodeCreateBatch2(batchInputs, txBackend)
|
|
@@ -9799,11 +10431,7 @@ function createNodeCollection(config) {
|
|
|
9799
10431
|
if (row !== void 0) existingMap.set(row.id, row);
|
|
9800
10432
|
}
|
|
9801
10433
|
} else {
|
|
9802
|
-
const rows = await target.getNodes(
|
|
9803
|
-
graphId,
|
|
9804
|
-
kind,
|
|
9805
|
-
ids
|
|
9806
|
-
);
|
|
10434
|
+
const rows = await target.getNodes(graphId, kind, ids);
|
|
9807
10435
|
for (const row of rows) {
|
|
9808
10436
|
existingMap.set(row.id, row);
|
|
9809
10437
|
}
|
|
@@ -9816,22 +10444,13 @@ function createNodeCollection(config) {
|
|
|
9816
10444
|
if (existing) {
|
|
9817
10445
|
toUpdate.push({
|
|
9818
10446
|
index: itemIndex,
|
|
9819
|
-
input: buildUpdateInput(
|
|
9820
|
-
kind,
|
|
9821
|
-
item.id,
|
|
9822
|
-
item.props,
|
|
9823
|
-
item
|
|
9824
|
-
),
|
|
10447
|
+
input: buildUpdateInput(kind, item.id, item.props, item),
|
|
9825
10448
|
clearDeleted: existing.deleted_at !== void 0
|
|
9826
10449
|
});
|
|
9827
10450
|
} else {
|
|
9828
10451
|
toCreate.push({
|
|
9829
10452
|
index: itemIndex,
|
|
9830
|
-
input: buildCreateInput(
|
|
9831
|
-
kind,
|
|
9832
|
-
item.props,
|
|
9833
|
-
item
|
|
9834
|
-
)
|
|
10453
|
+
input: buildCreateInput(kind, item.props, item)
|
|
9835
10454
|
});
|
|
9836
10455
|
}
|
|
9837
10456
|
itemIndex++;
|
|
@@ -9858,10 +10477,7 @@ function createNodeCollection(config) {
|
|
|
9858
10477
|
return upsertAll(backend);
|
|
9859
10478
|
},
|
|
9860
10479
|
async bulkInsert(items) {
|
|
9861
|
-
const batchInputs = mapBulkNodeInputs(
|
|
9862
|
-
kind,
|
|
9863
|
-
items
|
|
9864
|
-
);
|
|
10480
|
+
const batchInputs = mapBulkNodeInputs(kind, items);
|
|
9865
10481
|
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
9866
10482
|
await backend.transaction(async (txBackend) => {
|
|
9867
10483
|
await executeNodeCreateNoReturnBatch2(batchInputs, txBackend);
|
|
@@ -10394,12 +11010,12 @@ async function validateAndPrepareEdgeCreate(ctx, input, id, backend) {
|
|
|
10394
11010
|
nodeId: input.toId
|
|
10395
11011
|
});
|
|
10396
11012
|
}
|
|
10397
|
-
const validatedProps =
|
|
11013
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateEdgeProps(edgeKind.schema, input.props, {
|
|
10398
11014
|
kind,
|
|
10399
11015
|
operation: "create"
|
|
10400
11016
|
});
|
|
10401
|
-
const validFrom =
|
|
10402
|
-
const validTo =
|
|
11017
|
+
const validFrom = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validFrom, "validFrom");
|
|
11018
|
+
const validTo = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validTo, "validTo");
|
|
10403
11019
|
const cardinality = registration.cardinality ?? "many";
|
|
10404
11020
|
const constraintContext = {
|
|
10405
11021
|
graphId: ctx.graphId,
|
|
@@ -10544,12 +11160,12 @@ async function executeEdgeUpdate(ctx, input, backend) {
|
|
|
10544
11160
|
const edgeKind = registration.type;
|
|
10545
11161
|
const existingProps = JSON.parse(existing.props);
|
|
10546
11162
|
const mergedProps = { ...existingProps, ...input.props };
|
|
10547
|
-
const validatedProps =
|
|
11163
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateEdgeProps(edgeKind.schema, mergedProps, {
|
|
10548
11164
|
kind: existing.kind,
|
|
10549
11165
|
operation: "update",
|
|
10550
11166
|
id
|
|
10551
11167
|
});
|
|
10552
|
-
const validTo =
|
|
11168
|
+
const validTo = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validTo, "validTo");
|
|
10553
11169
|
const updateParams = {
|
|
10554
11170
|
graphId: ctx.graphId,
|
|
10555
11171
|
id,
|
|
@@ -10570,12 +11186,12 @@ async function executeEdgeUpsertUpdate(ctx, input, backend, options) {
|
|
|
10570
11186
|
const edgeKind = registration.type;
|
|
10571
11187
|
const existingProps = JSON.parse(existing.props);
|
|
10572
11188
|
const mergedProps = { ...existingProps, ...input.props };
|
|
10573
|
-
const validatedProps =
|
|
11189
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateEdgeProps(edgeKind.schema, mergedProps, {
|
|
10574
11190
|
kind: existing.kind,
|
|
10575
11191
|
operation: "update",
|
|
10576
11192
|
id
|
|
10577
11193
|
});
|
|
10578
|
-
const validTo =
|
|
11194
|
+
const validTo = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validTo, "validTo");
|
|
10579
11195
|
const updateParams = {
|
|
10580
11196
|
graphId: ctx.graphId,
|
|
10581
11197
|
id,
|
|
@@ -10727,7 +11343,7 @@ async function executeEdgeGetOrCreateByEndpoints(ctx, kind, fromKind, fromId, to
|
|
|
10727
11343
|
const matchOn = options?.matchOn ?? [];
|
|
10728
11344
|
const registration = getEdgeRegistration(ctx.graph, kind);
|
|
10729
11345
|
const edgeKind = registration.type;
|
|
10730
|
-
const validatedProps =
|
|
11346
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateEdgeProps(edgeKind.schema, props, {
|
|
10731
11347
|
kind,
|
|
10732
11348
|
operation: "create"
|
|
10733
11349
|
});
|
|
@@ -10809,7 +11425,7 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
10809
11425
|
validateMatchOnFields(edgeKind.schema, matchOn, kind);
|
|
10810
11426
|
const validated = [];
|
|
10811
11427
|
for (const item of items) {
|
|
10812
|
-
const validatedProps =
|
|
11428
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateEdgeProps(edgeKind.schema, item.props, {
|
|
10813
11429
|
kind,
|
|
10814
11430
|
operation: "create"
|
|
10815
11431
|
});
|
|
@@ -10967,15 +11583,19 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
10967
11583
|
}
|
|
10968
11584
|
|
|
10969
11585
|
// src/store/embedding-sync.ts
|
|
11586
|
+
var embeddingFieldsCache = /* @__PURE__ */ new WeakMap();
|
|
10970
11587
|
function getEmbeddingFields(schema) {
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
11588
|
+
const cached = embeddingFieldsCache.get(schema);
|
|
11589
|
+
if (cached) return cached;
|
|
11590
|
+
const fields = computeEmbeddingFields(schema);
|
|
11591
|
+
embeddingFieldsCache.set(schema, fields);
|
|
11592
|
+
return fields;
|
|
11593
|
+
}
|
|
11594
|
+
function computeEmbeddingFields(schema) {
|
|
11595
|
+
if (schema.type !== "object") return [];
|
|
10974
11596
|
const def = schema.def;
|
|
10975
11597
|
const shape = def.shape;
|
|
10976
|
-
if (!shape)
|
|
10977
|
-
return [];
|
|
10978
|
-
}
|
|
11598
|
+
if (!shape) return [];
|
|
10979
11599
|
const fields = [];
|
|
10980
11600
|
for (const [fieldPath, fieldSchema] of Object.entries(shape)) {
|
|
10981
11601
|
const dimensions = getEmbeddingDimensionsFromField(fieldSchema);
|
|
@@ -10986,13 +11606,13 @@ function getEmbeddingFields(schema) {
|
|
|
10986
11606
|
return fields;
|
|
10987
11607
|
}
|
|
10988
11608
|
function getEmbeddingDimensionsFromField(schema) {
|
|
10989
|
-
const directDimensions =
|
|
11609
|
+
const directDimensions = chunkUVZHTBZ5_cjs.getEmbeddingDimensions(schema);
|
|
10990
11610
|
if (directDimensions !== void 0) {
|
|
10991
11611
|
return directDimensions;
|
|
10992
11612
|
}
|
|
10993
11613
|
const unwrapped = unwrapToEmbedding(schema);
|
|
10994
11614
|
if (unwrapped) {
|
|
10995
|
-
return
|
|
11615
|
+
return chunkUVZHTBZ5_cjs.getEmbeddingDimensions(unwrapped);
|
|
10996
11616
|
}
|
|
10997
11617
|
return void 0;
|
|
10998
11618
|
}
|
|
@@ -11000,7 +11620,7 @@ function unwrapToEmbedding(schema) {
|
|
|
11000
11620
|
const type = schema.type;
|
|
11001
11621
|
const def = schema.def;
|
|
11002
11622
|
if ((type === "optional" || type === "nullable" || type === "default" || type === "readonly") && def.innerType) {
|
|
11003
|
-
if (
|
|
11623
|
+
if (chunkUVZHTBZ5_cjs.isEmbeddingSchema(def.innerType)) {
|
|
11004
11624
|
return def.innerType;
|
|
11005
11625
|
}
|
|
11006
11626
|
return unwrapToEmbedding(def.innerType);
|
|
@@ -11062,6 +11682,101 @@ function isValidEmbeddingValue(value) {
|
|
|
11062
11682
|
return value.every((n) => typeof n === "number" && Number.isFinite(n));
|
|
11063
11683
|
}
|
|
11064
11684
|
|
|
11685
|
+
// src/store/fulltext-sync.ts
|
|
11686
|
+
var searchableFieldsCache = /* @__PURE__ */ new WeakMap();
|
|
11687
|
+
function getSearchableFields(schema) {
|
|
11688
|
+
const cached = searchableFieldsCache.get(schema);
|
|
11689
|
+
if (cached) return cached;
|
|
11690
|
+
const fields = computeSearchableFields(schema);
|
|
11691
|
+
searchableFieldsCache.set(schema, fields);
|
|
11692
|
+
return fields;
|
|
11693
|
+
}
|
|
11694
|
+
function computeSearchableFields(schema) {
|
|
11695
|
+
if (schema.type !== "object") return [];
|
|
11696
|
+
const def = schema.def;
|
|
11697
|
+
const shape = def.shape;
|
|
11698
|
+
if (!shape) return [];
|
|
11699
|
+
const fields = [];
|
|
11700
|
+
for (const [fieldPath, fieldSchema] of Object.entries(shape)) {
|
|
11701
|
+
const metadata = chunkUVZHTBZ5_cjs.getSearchableMetadata(fieldSchema);
|
|
11702
|
+
if (metadata !== void 0) {
|
|
11703
|
+
fields.push({ fieldPath, metadata });
|
|
11704
|
+
}
|
|
11705
|
+
}
|
|
11706
|
+
warnIfConflictingLanguages(fields);
|
|
11707
|
+
return fields;
|
|
11708
|
+
}
|
|
11709
|
+
function warnIfConflictingLanguages(fields) {
|
|
11710
|
+
if (fields.length < 2) return;
|
|
11711
|
+
const languages = new Set(fields.map((field2) => field2.metadata.language));
|
|
11712
|
+
if (languages.size < 2) return;
|
|
11713
|
+
if (typeof console === "undefined" || typeof console.warn !== "function") {
|
|
11714
|
+
return;
|
|
11715
|
+
}
|
|
11716
|
+
const fieldSummary = fields.map((field2) => `${field2.fieldPath}=${field2.metadata.language}`).join(", ");
|
|
11717
|
+
const winning = fields[0]?.metadata.language ?? chunkUVZHTBZ5_cjs.DEFAULT_SEARCHABLE_LANGUAGE;
|
|
11718
|
+
console.warn(
|
|
11719
|
+
`[typegraph] searchable() fields declare conflicting languages (${fieldSummary}). The first field's language ("${winning}") is recorded on the fulltext row; true multilingual indexing requires a dedicated node kind per language.`
|
|
11720
|
+
);
|
|
11721
|
+
}
|
|
11722
|
+
var FIELD_SEPARATOR = "\n";
|
|
11723
|
+
function resolveCombinedLanguage(fields) {
|
|
11724
|
+
return fields[0]?.metadata.language ?? chunkUVZHTBZ5_cjs.DEFAULT_SEARCHABLE_LANGUAGE;
|
|
11725
|
+
}
|
|
11726
|
+
function computeFulltextContent(schema, props) {
|
|
11727
|
+
const searchableFields = getSearchableFields(schema);
|
|
11728
|
+
if (searchableFields.length === 0) return void 0;
|
|
11729
|
+
const parts = [];
|
|
11730
|
+
for (const field2 of searchableFields) {
|
|
11731
|
+
const value = props[field2.fieldPath];
|
|
11732
|
+
if (typeof value === "string" && value.length > 0) {
|
|
11733
|
+
parts.push(value);
|
|
11734
|
+
}
|
|
11735
|
+
}
|
|
11736
|
+
if (parts.length === 0) return void 0;
|
|
11737
|
+
return {
|
|
11738
|
+
content: parts.join(FIELD_SEPARATOR),
|
|
11739
|
+
language: resolveCombinedLanguage(searchableFields)
|
|
11740
|
+
};
|
|
11741
|
+
}
|
|
11742
|
+
async function syncFulltext(ctx, schema, props) {
|
|
11743
|
+
const { backend } = ctx;
|
|
11744
|
+
if (!backend.upsertFulltext || !backend.deleteFulltext) {
|
|
11745
|
+
return;
|
|
11746
|
+
}
|
|
11747
|
+
const computed = computeFulltextContent(schema, props);
|
|
11748
|
+
if (computed !== void 0) {
|
|
11749
|
+
await backend.upsertFulltext({
|
|
11750
|
+
graphId: ctx.graphId,
|
|
11751
|
+
nodeKind: ctx.nodeKind,
|
|
11752
|
+
nodeId: ctx.nodeId,
|
|
11753
|
+
content: computed.content,
|
|
11754
|
+
language: computed.language
|
|
11755
|
+
});
|
|
11756
|
+
return;
|
|
11757
|
+
}
|
|
11758
|
+
if (getSearchableFields(schema).length === 0) return;
|
|
11759
|
+
await backend.deleteFulltext({
|
|
11760
|
+
graphId: ctx.graphId,
|
|
11761
|
+
nodeKind: ctx.nodeKind,
|
|
11762
|
+
nodeId: ctx.nodeId
|
|
11763
|
+
});
|
|
11764
|
+
}
|
|
11765
|
+
async function deleteNodeFulltext(ctx, schema) {
|
|
11766
|
+
const { backend } = ctx;
|
|
11767
|
+
if (!backend.deleteFulltext) {
|
|
11768
|
+
return;
|
|
11769
|
+
}
|
|
11770
|
+
if (getSearchableFields(schema).length === 0) {
|
|
11771
|
+
return;
|
|
11772
|
+
}
|
|
11773
|
+
await backend.deleteFulltext({
|
|
11774
|
+
graphId: ctx.graphId,
|
|
11775
|
+
nodeKind: ctx.nodeKind,
|
|
11776
|
+
nodeId: ctx.nodeId
|
|
11777
|
+
});
|
|
11778
|
+
}
|
|
11779
|
+
|
|
11065
11780
|
// src/store/uniqueness.ts
|
|
11066
11781
|
async function checkUniquenessConstraints(ctx, kind, id, props, constraints) {
|
|
11067
11782
|
for (const constraint of constraints) {
|
|
@@ -11255,6 +11970,9 @@ function createUniquenessContext(graphId, registry, backend) {
|
|
|
11255
11970
|
function createEmbeddingSyncContext(graphId, nodeKind, nodeId, backend) {
|
|
11256
11971
|
return { graphId, nodeKind, nodeId, backend };
|
|
11257
11972
|
}
|
|
11973
|
+
function createFulltextSyncContext(graphId, nodeKind, nodeId, backend) {
|
|
11974
|
+
return { graphId, nodeKind, nodeId, backend };
|
|
11975
|
+
}
|
|
11258
11976
|
function createNodeBatchValidationBackend(graphId, registry, backend) {
|
|
11259
11977
|
const nodeCache = /* @__PURE__ */ new Map();
|
|
11260
11978
|
const pendingNodes = /* @__PURE__ */ new Map();
|
|
@@ -11354,12 +12072,12 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend) {
|
|
|
11354
12072
|
const kind = input.kind;
|
|
11355
12073
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11356
12074
|
const nodeKind = registration.type;
|
|
11357
|
-
const validatedProps =
|
|
12075
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateNodeProps(nodeKind.schema, input.props, {
|
|
11358
12076
|
kind,
|
|
11359
12077
|
operation: "create"
|
|
11360
12078
|
});
|
|
11361
|
-
const validFrom =
|
|
11362
|
-
const validTo =
|
|
12079
|
+
const validFrom = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validFrom, "validFrom");
|
|
12080
|
+
const validTo = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validTo, "validTo");
|
|
11363
12081
|
const existingNode = await backend.getNode(ctx.graphId, kind, id);
|
|
11364
12082
|
if (existingNode && !existingNode.deleted_at) {
|
|
11365
12083
|
throw createNodeAlreadyExistsError(kind, id);
|
|
@@ -11412,6 +12130,11 @@ async function finalizeNodeCreate(ctx, prepared, backend) {
|
|
|
11412
12130
|
prepared.nodeKind.schema,
|
|
11413
12131
|
prepared.validatedProps
|
|
11414
12132
|
);
|
|
12133
|
+
await syncFulltext(
|
|
12134
|
+
createFulltextSyncContext(ctx.graphId, prepared.kind, prepared.id, backend),
|
|
12135
|
+
prepared.nodeKind.schema,
|
|
12136
|
+
prepared.validatedProps
|
|
12137
|
+
);
|
|
11415
12138
|
}
|
|
11416
12139
|
async function performNodeUpdate(ctx, input, backend, options) {
|
|
11417
12140
|
const { kind, id } = input;
|
|
@@ -11423,12 +12146,12 @@ async function performNodeUpdate(ctx, input, backend, options) {
|
|
|
11423
12146
|
const existingProps = JSON.parse(existing.props);
|
|
11424
12147
|
const mergedProps = { ...existingProps, ...input.props };
|
|
11425
12148
|
const nodeKind = registration.type;
|
|
11426
|
-
const validatedProps =
|
|
12149
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateNodeProps(nodeKind.schema, mergedProps, {
|
|
11427
12150
|
kind,
|
|
11428
12151
|
operation: "update",
|
|
11429
12152
|
id
|
|
11430
12153
|
});
|
|
11431
|
-
const validTo =
|
|
12154
|
+
const validTo = chunkWRWVWKQL_cjs.validateOptionalIsoDate(input.validTo, "validTo");
|
|
11432
12155
|
await updateUniquenessEntries(
|
|
11433
12156
|
createUniquenessContext(ctx.graphId, ctx.registry, backend),
|
|
11434
12157
|
kind,
|
|
@@ -11452,6 +12175,11 @@ async function performNodeUpdate(ctx, input, backend, options) {
|
|
|
11452
12175
|
nodeKind.schema,
|
|
11453
12176
|
validatedProps
|
|
11454
12177
|
);
|
|
12178
|
+
await syncFulltext(
|
|
12179
|
+
createFulltextSyncContext(ctx.graphId, kind, id, backend),
|
|
12180
|
+
nodeKind.schema,
|
|
12181
|
+
validatedProps
|
|
12182
|
+
);
|
|
11455
12183
|
return rowToNode(row);
|
|
11456
12184
|
}
|
|
11457
12185
|
async function enforceDeleteBehavior(ctx, kind, id, mode, backend, registration) {
|
|
@@ -11668,6 +12396,10 @@ async function executeNodeDelete(ctx, kind, id, backend) {
|
|
|
11668
12396
|
createEmbeddingSyncContext(ctx.graphId, kind, id, backend),
|
|
11669
12397
|
nodeKind.schema
|
|
11670
12398
|
);
|
|
12399
|
+
await deleteNodeFulltext(
|
|
12400
|
+
createFulltextSyncContext(ctx.graphId, kind, id, backend),
|
|
12401
|
+
nodeKind.schema
|
|
12402
|
+
);
|
|
11671
12403
|
});
|
|
11672
12404
|
}
|
|
11673
12405
|
async function executeNodeHardDelete(ctx, kind, id, backend) {
|
|
@@ -11687,7 +12419,7 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
|
|
|
11687
12419
|
const ifExists = options?.ifExists ?? "return";
|
|
11688
12420
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11689
12421
|
const nodeKind = registration.type;
|
|
11690
|
-
const validatedProps =
|
|
12422
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateNodeProps(nodeKind.schema, props, {
|
|
11691
12423
|
kind,
|
|
11692
12424
|
operation: "create"
|
|
11693
12425
|
});
|
|
@@ -11759,7 +12491,7 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
|
|
|
11759
12491
|
async function executeNodeFindByConstraint(ctx, kind, constraintName, props, backend) {
|
|
11760
12492
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11761
12493
|
const nodeKind = registration.type;
|
|
11762
|
-
const validatedProps =
|
|
12494
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateNodeProps(nodeKind.schema, props, {
|
|
11763
12495
|
kind,
|
|
11764
12496
|
operation: "create"
|
|
11765
12497
|
});
|
|
@@ -11796,7 +12528,7 @@ async function executeNodeFindByConstraint(ctx, kind, constraintName, props, bac
|
|
|
11796
12528
|
function validateAndComputeKeys(nodeKind, kind, constraint, items) {
|
|
11797
12529
|
const validated = [];
|
|
11798
12530
|
for (const item of items) {
|
|
11799
|
-
const validatedProps =
|
|
12531
|
+
const validatedProps = chunkHRNQ3DVJ_cjs.validateNodeProps(nodeKind.schema, item.props, {
|
|
11800
12532
|
kind,
|
|
11801
12533
|
operation: "create"
|
|
11802
12534
|
});
|
|
@@ -11974,6 +12706,503 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11974
12706
|
return results;
|
|
11975
12707
|
}
|
|
11976
12708
|
|
|
12709
|
+
// src/store/fulltext-rebuild.ts
|
|
12710
|
+
var DEFAULT_PAGE_SIZE = 500;
|
|
12711
|
+
var DEFAULT_MAX_SKIPPED_IDS = 1e4;
|
|
12712
|
+
function validatePageSize(value) {
|
|
12713
|
+
if (value === void 0) return DEFAULT_PAGE_SIZE;
|
|
12714
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
12715
|
+
throw new chunkO5PST6TB_cjs.ValidationError(
|
|
12716
|
+
`pageSize must be a positive integer, got: ${String(value)}`,
|
|
12717
|
+
{
|
|
12718
|
+
issues: [{ path: "pageSize", message: "Must be a positive integer." }]
|
|
12719
|
+
}
|
|
12720
|
+
);
|
|
12721
|
+
}
|
|
12722
|
+
return value;
|
|
12723
|
+
}
|
|
12724
|
+
function validateMaxSkippedIds(value) {
|
|
12725
|
+
if (value === void 0) return DEFAULT_MAX_SKIPPED_IDS;
|
|
12726
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
12727
|
+
throw new chunkO5PST6TB_cjs.ValidationError(
|
|
12728
|
+
`maxSkippedIds must be a non-negative integer, got: ${String(value)}`,
|
|
12729
|
+
{
|
|
12730
|
+
issues: [
|
|
12731
|
+
{
|
|
12732
|
+
path: "maxSkippedIds",
|
|
12733
|
+
message: "Must be a non-negative integer."
|
|
12734
|
+
}
|
|
12735
|
+
]
|
|
12736
|
+
}
|
|
12737
|
+
);
|
|
12738
|
+
}
|
|
12739
|
+
return value;
|
|
12740
|
+
}
|
|
12741
|
+
function isPropsObject(value) {
|
|
12742
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12743
|
+
}
|
|
12744
|
+
async function rebuildFulltextIndex(ctx, nodeKind, options) {
|
|
12745
|
+
const { backend, registry } = ctx;
|
|
12746
|
+
if (!backend.upsertFulltext || !backend.deleteFulltext) {
|
|
12747
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
12748
|
+
"Backend does not support fulltext; cannot rebuild index",
|
|
12749
|
+
{ backend: backend.dialect, capability: "fulltext" }
|
|
12750
|
+
);
|
|
12751
|
+
}
|
|
12752
|
+
const pageSize = validatePageSize(options.pageSize);
|
|
12753
|
+
const maxSkippedIds = validateMaxSkippedIds(options.maxSkippedIds);
|
|
12754
|
+
const targetKinds = nodeKind === void 0 ? [...registry.nodeKinds.keys()] : [nodeKind];
|
|
12755
|
+
const rebuiltKinds = [];
|
|
12756
|
+
let processed = 0;
|
|
12757
|
+
let upserted = 0;
|
|
12758
|
+
let cleared = 0;
|
|
12759
|
+
let skipped = 0;
|
|
12760
|
+
const skippedIds = [];
|
|
12761
|
+
for (const kind of targetKinds) {
|
|
12762
|
+
const nodeType = registry.getNodeType(kind);
|
|
12763
|
+
if (!nodeType) {
|
|
12764
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(`Unknown node kind: ${kind}`, { kind });
|
|
12765
|
+
}
|
|
12766
|
+
if (getSearchableFields(nodeType.schema).length === 0) {
|
|
12767
|
+
continue;
|
|
12768
|
+
}
|
|
12769
|
+
rebuiltKinds.push(kind);
|
|
12770
|
+
let cursor;
|
|
12771
|
+
for (; ; ) {
|
|
12772
|
+
const rows = await backend.findNodesByKind({
|
|
12773
|
+
graphId: ctx.graphId,
|
|
12774
|
+
kind,
|
|
12775
|
+
limit: pageSize,
|
|
12776
|
+
excludeDeleted: false,
|
|
12777
|
+
orderBy: "id",
|
|
12778
|
+
...cursor === void 0 ? {} : { after: cursor }
|
|
12779
|
+
});
|
|
12780
|
+
if (rows.length === 0) break;
|
|
12781
|
+
const pageResult = processPage(nodeType.schema, rows);
|
|
12782
|
+
skipped += pageResult.skipped;
|
|
12783
|
+
const remaining = maxSkippedIds - skippedIds.length;
|
|
12784
|
+
if (remaining > 0 && pageResult.skippedIds.length > 0) {
|
|
12785
|
+
skippedIds.push(...pageResult.skippedIds.slice(0, remaining));
|
|
12786
|
+
}
|
|
12787
|
+
await backend.transaction(async (tx) => {
|
|
12788
|
+
if (pageResult.toUpsert.length > 0) {
|
|
12789
|
+
if (tx.upsertFulltextBatch) {
|
|
12790
|
+
await tx.upsertFulltextBatch({
|
|
12791
|
+
graphId: ctx.graphId,
|
|
12792
|
+
nodeKind: kind,
|
|
12793
|
+
rows: pageResult.toUpsert
|
|
12794
|
+
});
|
|
12795
|
+
} else if (tx.upsertFulltext) {
|
|
12796
|
+
for (const item of pageResult.toUpsert) {
|
|
12797
|
+
await tx.upsertFulltext({
|
|
12798
|
+
graphId: ctx.graphId,
|
|
12799
|
+
nodeKind: kind,
|
|
12800
|
+
nodeId: item.nodeId,
|
|
12801
|
+
content: item.content,
|
|
12802
|
+
language: item.language
|
|
12803
|
+
});
|
|
12804
|
+
}
|
|
12805
|
+
}
|
|
12806
|
+
}
|
|
12807
|
+
if (pageResult.toDelete.length > 0) {
|
|
12808
|
+
if (tx.deleteFulltextBatch) {
|
|
12809
|
+
await tx.deleteFulltextBatch({
|
|
12810
|
+
graphId: ctx.graphId,
|
|
12811
|
+
nodeKind: kind,
|
|
12812
|
+
nodeIds: pageResult.toDelete
|
|
12813
|
+
});
|
|
12814
|
+
} else if (tx.deleteFulltext) {
|
|
12815
|
+
for (const nodeId of pageResult.toDelete) {
|
|
12816
|
+
await tx.deleteFulltext({
|
|
12817
|
+
graphId: ctx.graphId,
|
|
12818
|
+
nodeKind: kind,
|
|
12819
|
+
nodeId
|
|
12820
|
+
});
|
|
12821
|
+
}
|
|
12822
|
+
}
|
|
12823
|
+
}
|
|
12824
|
+
});
|
|
12825
|
+
processed += rows.length;
|
|
12826
|
+
upserted += pageResult.toUpsert.length;
|
|
12827
|
+
cleared += pageResult.toDelete.length;
|
|
12828
|
+
const lastRow = rows.at(-1);
|
|
12829
|
+
if (!lastRow) break;
|
|
12830
|
+
cursor = lastRow.id;
|
|
12831
|
+
if (rows.length < pageSize) break;
|
|
12832
|
+
}
|
|
12833
|
+
}
|
|
12834
|
+
return {
|
|
12835
|
+
kinds: rebuiltKinds,
|
|
12836
|
+
processed,
|
|
12837
|
+
upserted,
|
|
12838
|
+
cleared,
|
|
12839
|
+
skipped,
|
|
12840
|
+
skippedIds,
|
|
12841
|
+
skippedTruncated: skipped > skippedIds.length
|
|
12842
|
+
};
|
|
12843
|
+
}
|
|
12844
|
+
function processPage(schema, rows) {
|
|
12845
|
+
const toUpsert = [];
|
|
12846
|
+
const toDelete = [];
|
|
12847
|
+
const skippedIds = [];
|
|
12848
|
+
let skipped = 0;
|
|
12849
|
+
for (const row of rows) {
|
|
12850
|
+
if (row.deleted_at !== void 0) {
|
|
12851
|
+
toDelete.push(row.id);
|
|
12852
|
+
continue;
|
|
12853
|
+
}
|
|
12854
|
+
let parsed;
|
|
12855
|
+
try {
|
|
12856
|
+
parsed = JSON.parse(row.props);
|
|
12857
|
+
} catch {
|
|
12858
|
+
skipped += 1;
|
|
12859
|
+
skippedIds.push(row.id);
|
|
12860
|
+
continue;
|
|
12861
|
+
}
|
|
12862
|
+
if (!isPropsObject(parsed)) {
|
|
12863
|
+
skipped += 1;
|
|
12864
|
+
skippedIds.push(row.id);
|
|
12865
|
+
continue;
|
|
12866
|
+
}
|
|
12867
|
+
const computed = computeFulltextContent(schema, parsed);
|
|
12868
|
+
if (computed === void 0) {
|
|
12869
|
+
toDelete.push(row.id);
|
|
12870
|
+
} else {
|
|
12871
|
+
toUpsert.push({
|
|
12872
|
+
nodeId: row.id,
|
|
12873
|
+
content: computed.content,
|
|
12874
|
+
language: computed.language
|
|
12875
|
+
});
|
|
12876
|
+
}
|
|
12877
|
+
}
|
|
12878
|
+
return { toUpsert, toDelete, skipped, skippedIds };
|
|
12879
|
+
}
|
|
12880
|
+
|
|
12881
|
+
// src/store/search.ts
|
|
12882
|
+
async function executeFulltextSearch(ctx, nodeKind, options) {
|
|
12883
|
+
const { backend, graphId } = ctx;
|
|
12884
|
+
if (!backend.fulltextSearch) {
|
|
12885
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError("Backend does not support fulltext search", {
|
|
12886
|
+
backend: backend.dialect,
|
|
12887
|
+
capability: "fulltext"
|
|
12888
|
+
});
|
|
12889
|
+
}
|
|
12890
|
+
if (!Number.isInteger(options.limit) || options.limit <= 0) {
|
|
12891
|
+
throw new RangeError(
|
|
12892
|
+
`fulltextSearch.limit must be a positive integer, got: ${options.limit}`
|
|
12893
|
+
);
|
|
12894
|
+
}
|
|
12895
|
+
validateFulltextCallOptions(backend, {
|
|
12896
|
+
mode: options.mode,
|
|
12897
|
+
includeSnippets: options.includeSnippets,
|
|
12898
|
+
language: options.language
|
|
12899
|
+
});
|
|
12900
|
+
const params = {
|
|
12901
|
+
graphId,
|
|
12902
|
+
nodeKind,
|
|
12903
|
+
query: options.query,
|
|
12904
|
+
limit: options.limit,
|
|
12905
|
+
...options.mode ? { mode: options.mode } : {},
|
|
12906
|
+
...options.language ? { language: options.language } : {},
|
|
12907
|
+
...options.minScore === void 0 ? {} : { minScore: options.minScore },
|
|
12908
|
+
...options.includeSnippets === void 0 ? {} : { includeSnippets: options.includeSnippets }
|
|
12909
|
+
};
|
|
12910
|
+
const rows = await backend.fulltextSearch(params);
|
|
12911
|
+
if (rows.length === 0) return [];
|
|
12912
|
+
const ids = rows.map((r) => r.nodeId);
|
|
12913
|
+
const nodeMap = await fetchNodesByIds(backend, graphId, nodeKind, ids);
|
|
12914
|
+
const hits = [];
|
|
12915
|
+
let rank = 1;
|
|
12916
|
+
for (const row of rows) {
|
|
12917
|
+
const node = nodeMap.get(row.nodeId);
|
|
12918
|
+
if (!node) continue;
|
|
12919
|
+
hits.push({
|
|
12920
|
+
node,
|
|
12921
|
+
score: row.score,
|
|
12922
|
+
rank,
|
|
12923
|
+
...row.snippet === void 0 ? {} : { snippet: row.snippet }
|
|
12924
|
+
});
|
|
12925
|
+
rank += 1;
|
|
12926
|
+
}
|
|
12927
|
+
return hits;
|
|
12928
|
+
}
|
|
12929
|
+
async function executeHybridSearch(ctx, nodeKind, options) {
|
|
12930
|
+
const { backend, graphId } = ctx;
|
|
12931
|
+
if (!backend.vectorSearch) {
|
|
12932
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError("Backend does not support vector search", {
|
|
12933
|
+
backend: backend.dialect,
|
|
12934
|
+
capability: "vector"
|
|
12935
|
+
});
|
|
12936
|
+
}
|
|
12937
|
+
if (!backend.fulltextSearch) {
|
|
12938
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError("Backend does not support fulltext search", {
|
|
12939
|
+
backend: backend.dialect,
|
|
12940
|
+
capability: "fulltext"
|
|
12941
|
+
});
|
|
12942
|
+
}
|
|
12943
|
+
if (!Number.isInteger(options.limit) || options.limit <= 0) {
|
|
12944
|
+
throw new RangeError(
|
|
12945
|
+
`hybridSearch.limit must be a positive integer, got: ${options.limit}`
|
|
12946
|
+
);
|
|
12947
|
+
}
|
|
12948
|
+
if (options.fusion !== void 0) {
|
|
12949
|
+
validateHybridFusionOptions(options.fusion);
|
|
12950
|
+
}
|
|
12951
|
+
validateFulltextCallOptions(backend, {
|
|
12952
|
+
mode: options.fulltext.mode,
|
|
12953
|
+
includeSnippets: options.fulltext.includeSnippets,
|
|
12954
|
+
language: options.fulltext.language
|
|
12955
|
+
});
|
|
12956
|
+
const fusionK = options.fusion?.k ?? DEFAULT_RRF_K;
|
|
12957
|
+
const vectorWeight = options.fusion?.weights?.vector ?? DEFAULT_RRF_WEIGHT;
|
|
12958
|
+
const fulltextWeight = options.fusion?.weights?.fulltext ?? DEFAULT_RRF_WEIGHT;
|
|
12959
|
+
const overFetchMultiplier = 4;
|
|
12960
|
+
const vectorK = options.vector.k ?? options.limit * overFetchMultiplier;
|
|
12961
|
+
const fulltextK = options.fulltext.k ?? options.limit * overFetchMultiplier;
|
|
12962
|
+
const vectorPromise = backend.vectorSearch({
|
|
12963
|
+
graphId,
|
|
12964
|
+
nodeKind,
|
|
12965
|
+
fieldPath: options.vector.fieldPath,
|
|
12966
|
+
queryEmbedding: options.vector.queryEmbedding,
|
|
12967
|
+
metric: options.vector.metric ?? "cosine",
|
|
12968
|
+
limit: vectorK,
|
|
12969
|
+
...options.vector.minScore === void 0 ? {} : { minScore: options.vector.minScore }
|
|
12970
|
+
});
|
|
12971
|
+
const fulltextPromise = backend.fulltextSearch({
|
|
12972
|
+
graphId,
|
|
12973
|
+
nodeKind,
|
|
12974
|
+
query: options.fulltext.query,
|
|
12975
|
+
limit: fulltextK,
|
|
12976
|
+
...options.fulltext.mode ? { mode: options.fulltext.mode } : {},
|
|
12977
|
+
...options.fulltext.language ? { language: options.fulltext.language } : {},
|
|
12978
|
+
...options.fulltext.minScore === void 0 ? {} : { minScore: options.fulltext.minScore },
|
|
12979
|
+
...options.fulltext.includeSnippets === void 0 ? {} : { includeSnippets: options.fulltext.includeSnippets }
|
|
12980
|
+
});
|
|
12981
|
+
const [vectorRows, fulltextRows] = await Promise.all([
|
|
12982
|
+
vectorPromise,
|
|
12983
|
+
fulltextPromise
|
|
12984
|
+
]);
|
|
12985
|
+
const fused = /* @__PURE__ */ new Map();
|
|
12986
|
+
for (const [index, row] of vectorRows.entries()) {
|
|
12987
|
+
const rank2 = index + 1;
|
|
12988
|
+
const contribution = vectorWeight / (fusionK + rank2);
|
|
12989
|
+
const entry = fused.get(row.nodeId) ?? {
|
|
12990
|
+
nodeId: row.nodeId,
|
|
12991
|
+
fusedScore: 0
|
|
12992
|
+
};
|
|
12993
|
+
entry.fusedScore += contribution;
|
|
12994
|
+
entry.vectorRank = rank2;
|
|
12995
|
+
entry.vectorScore = row.score;
|
|
12996
|
+
fused.set(row.nodeId, entry);
|
|
12997
|
+
}
|
|
12998
|
+
for (const [index, row] of fulltextRows.entries()) {
|
|
12999
|
+
const rank2 = index + 1;
|
|
13000
|
+
const contribution = fulltextWeight / (fusionK + rank2);
|
|
13001
|
+
const entry = fused.get(row.nodeId) ?? {
|
|
13002
|
+
nodeId: row.nodeId,
|
|
13003
|
+
fusedScore: 0
|
|
13004
|
+
};
|
|
13005
|
+
entry.fusedScore += contribution;
|
|
13006
|
+
entry.fulltextRank = rank2;
|
|
13007
|
+
entry.fulltextScore = row.score;
|
|
13008
|
+
if (row.snippet !== void 0) {
|
|
13009
|
+
entry.fulltextSnippet = row.snippet;
|
|
13010
|
+
}
|
|
13011
|
+
fused.set(row.nodeId, entry);
|
|
13012
|
+
}
|
|
13013
|
+
const ranked = [...fused.values()].toSorted(
|
|
13014
|
+
(a, b) => b.fusedScore - a.fusedScore || a.nodeId.localeCompare(b.nodeId)
|
|
13015
|
+
).slice(0, options.limit);
|
|
13016
|
+
const ids = ranked.map((entry) => entry.nodeId);
|
|
13017
|
+
const nodeMap = await fetchNodesByIds(backend, graphId, nodeKind, ids);
|
|
13018
|
+
const hits = [];
|
|
13019
|
+
let rank = 1;
|
|
13020
|
+
for (const entry of ranked) {
|
|
13021
|
+
const node = nodeMap.get(entry.nodeId);
|
|
13022
|
+
if (!node) continue;
|
|
13023
|
+
const typedNode = node;
|
|
13024
|
+
const hit = {
|
|
13025
|
+
node: typedNode,
|
|
13026
|
+
score: entry.fusedScore,
|
|
13027
|
+
rank,
|
|
13028
|
+
...entry.vectorRank !== void 0 && entry.vectorScore !== void 0 ? {
|
|
13029
|
+
vector: {
|
|
13030
|
+
node: typedNode,
|
|
13031
|
+
score: entry.vectorScore,
|
|
13032
|
+
rank: entry.vectorRank
|
|
13033
|
+
}
|
|
13034
|
+
} : {},
|
|
13035
|
+
...entry.fulltextRank !== void 0 && entry.fulltextScore !== void 0 ? {
|
|
13036
|
+
fulltext: {
|
|
13037
|
+
node: typedNode,
|
|
13038
|
+
score: entry.fulltextScore,
|
|
13039
|
+
rank: entry.fulltextRank,
|
|
13040
|
+
...entry.fulltextSnippet === void 0 ? {} : { snippet: entry.fulltextSnippet }
|
|
13041
|
+
}
|
|
13042
|
+
} : {}
|
|
13043
|
+
};
|
|
13044
|
+
hits.push(hit);
|
|
13045
|
+
rank += 1;
|
|
13046
|
+
}
|
|
13047
|
+
return hits;
|
|
13048
|
+
}
|
|
13049
|
+
function validateFulltextCallOptions(backend, options) {
|
|
13050
|
+
const strategy = backend.fulltextStrategy;
|
|
13051
|
+
const capabilities = backend.capabilities.fulltext;
|
|
13052
|
+
if (options.mode !== void 0) {
|
|
13053
|
+
validateFulltextMode(backend, strategy, capabilities, options.mode);
|
|
13054
|
+
}
|
|
13055
|
+
if (options.includeSnippets === true) {
|
|
13056
|
+
validateFulltextSnippets(backend, strategy, capabilities);
|
|
13057
|
+
}
|
|
13058
|
+
if (options.language !== void 0) {
|
|
13059
|
+
validateFulltextLanguageOption(
|
|
13060
|
+
backend,
|
|
13061
|
+
strategy,
|
|
13062
|
+
capabilities,
|
|
13063
|
+
options.language
|
|
13064
|
+
);
|
|
13065
|
+
}
|
|
13066
|
+
}
|
|
13067
|
+
function validateFulltextMode(backend, strategy, capabilities, mode) {
|
|
13068
|
+
if (strategy !== void 0) {
|
|
13069
|
+
if (strategy.supportedModes.includes(mode)) return;
|
|
13070
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
13071
|
+
`Backend "${backend.dialect}" fulltext strategy "${strategy.name}" does not support mode "${mode}". Supported modes: ${strategy.supportedModes.join(", ")}`,
|
|
13072
|
+
{
|
|
13073
|
+
backend: backend.dialect,
|
|
13074
|
+
strategy: strategy.name,
|
|
13075
|
+
capability: `fulltext.modes.${mode}`
|
|
13076
|
+
}
|
|
13077
|
+
);
|
|
13078
|
+
}
|
|
13079
|
+
if (mode === "phrase" && capabilities && !capabilities.phraseQueries) {
|
|
13080
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
13081
|
+
`Backend "${backend.dialect}" does not support phrase queries`,
|
|
13082
|
+
{ backend: backend.dialect, capability: "fulltext.phraseQueries" }
|
|
13083
|
+
);
|
|
13084
|
+
}
|
|
13085
|
+
}
|
|
13086
|
+
function validateFulltextSnippets(backend, strategy, capabilities) {
|
|
13087
|
+
const supportsSnippets = strategy === void 0 ? capabilities?.highlighting !== false : strategy.supportsSnippets;
|
|
13088
|
+
if (supportsSnippets) return;
|
|
13089
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
13090
|
+
`Backend "${backend.dialect}" does not support snippet highlighting; drop includeSnippets or switch to a backend where highlighting is supported`,
|
|
13091
|
+
{ backend: backend.dialect, capability: "fulltext.highlighting" }
|
|
13092
|
+
);
|
|
13093
|
+
}
|
|
13094
|
+
function validateFulltextLanguageOption(backend, strategy, capabilities, language) {
|
|
13095
|
+
if (strategy !== void 0 && !strategy.supportsLanguageOverride) {
|
|
13096
|
+
throw new chunkO5PST6TB_cjs.ConfigurationError(
|
|
13097
|
+
`Backend "${backend.dialect}" fulltext strategy "${strategy.name}" does not honor a per-query \`language\` override (its tokenizer is fixed at table-create time). Drop the option, or pick a strategy that advertises \`supportsLanguageOverride: true\`.`,
|
|
13098
|
+
{
|
|
13099
|
+
backend: backend.dialect,
|
|
13100
|
+
strategy: strategy.name,
|
|
13101
|
+
capability: "fulltext.languageOverride"
|
|
13102
|
+
}
|
|
13103
|
+
);
|
|
13104
|
+
}
|
|
13105
|
+
if (capabilities !== void 0) {
|
|
13106
|
+
warnIfLanguageNotAdvertised(backend.dialect, capabilities, language);
|
|
13107
|
+
}
|
|
13108
|
+
}
|
|
13109
|
+
function warnIfLanguageNotAdvertised(dialect, capabilities, language) {
|
|
13110
|
+
if (capabilities.languages.length === 0) return;
|
|
13111
|
+
if (capabilities.languages.includes(language)) return;
|
|
13112
|
+
if (typeof console === "undefined" || typeof console.warn !== "function") {
|
|
13113
|
+
return;
|
|
13114
|
+
}
|
|
13115
|
+
console.warn(
|
|
13116
|
+
`[typegraph] fulltext language "${language}" is not in the advertised list for dialect "${dialect}" (${capabilities.languages.join(", ")}). If your backend has this language installed this warning is safe to ignore.`
|
|
13117
|
+
);
|
|
13118
|
+
}
|
|
13119
|
+
async function fetchNodesByIds(backend, graphId, nodeKind, ids) {
|
|
13120
|
+
if (ids.length === 0) return /* @__PURE__ */ new Map();
|
|
13121
|
+
const map = /* @__PURE__ */ new Map();
|
|
13122
|
+
if (backend.getNodes) {
|
|
13123
|
+
const rows = await backend.getNodes(graphId, nodeKind, ids);
|
|
13124
|
+
for (const row of rows) {
|
|
13125
|
+
if (row.deleted_at !== void 0) continue;
|
|
13126
|
+
map.set(row.id, rowToNode(row));
|
|
13127
|
+
}
|
|
13128
|
+
return map;
|
|
13129
|
+
}
|
|
13130
|
+
for (const id of ids) {
|
|
13131
|
+
const row = await backend.getNode(graphId, nodeKind, id);
|
|
13132
|
+
if (row && row.deleted_at === void 0) map.set(row.id, rowToNode(row));
|
|
13133
|
+
}
|
|
13134
|
+
return map;
|
|
13135
|
+
}
|
|
13136
|
+
|
|
13137
|
+
// src/store/search-facade.ts
|
|
13138
|
+
var StoreSearch = class {
|
|
13139
|
+
#context;
|
|
13140
|
+
constructor(context) {
|
|
13141
|
+
this.#context = context;
|
|
13142
|
+
}
|
|
13143
|
+
/**
|
|
13144
|
+
* Runs a fulltext search against nodes of the given kind.
|
|
13145
|
+
*
|
|
13146
|
+
* Requires fields on the node schema declared with `searchable()`.
|
|
13147
|
+
* The search hits the backend's fulltext index (tsvector + GIN on
|
|
13148
|
+
* Postgres, FTS5 on SQLite — or whatever strategy the backend is
|
|
13149
|
+
* configured with) and resolves the matching node IDs back to typed
|
|
13150
|
+
* `Node` objects.
|
|
13151
|
+
*/
|
|
13152
|
+
async fulltext(nodeKind, options) {
|
|
13153
|
+
return executeFulltextSearch(
|
|
13154
|
+
{ graphId: this.#context.graphId, backend: this.#context.backend },
|
|
13155
|
+
nodeKind,
|
|
13156
|
+
options
|
|
13157
|
+
);
|
|
13158
|
+
}
|
|
13159
|
+
/**
|
|
13160
|
+
* Runs a vector + fulltext hybrid search and fuses the results with
|
|
13161
|
+
* Reciprocal Rank Fusion.
|
|
13162
|
+
*
|
|
13163
|
+
* RRF is rank-based, so it composes well across heterogeneous score
|
|
13164
|
+
* scales (cosine similarity vs ts_rank_cd vs FTS5 BM25). Default
|
|
13165
|
+
* over-fetch is 4× `limit` from each source — tune via `vector.k` /
|
|
13166
|
+
* `fulltext.k` for higher-recall corpora.
|
|
13167
|
+
*/
|
|
13168
|
+
async hybrid(nodeKind, options) {
|
|
13169
|
+
return executeHybridSearch(
|
|
13170
|
+
{ graphId: this.#context.graphId, backend: this.#context.backend },
|
|
13171
|
+
nodeKind,
|
|
13172
|
+
options
|
|
13173
|
+
);
|
|
13174
|
+
}
|
|
13175
|
+
/**
|
|
13176
|
+
* Rebuilds the fulltext index from existing node data.
|
|
13177
|
+
*
|
|
13178
|
+
* Use when:
|
|
13179
|
+
* - A node kind gained a `searchable()` field after data was already
|
|
13180
|
+
* written and existing rows were never indexed.
|
|
13181
|
+
* - The fulltext table was dropped / truncated.
|
|
13182
|
+
* - `language` was changed on a `searchable()` field.
|
|
13183
|
+
*
|
|
13184
|
+
* Iterates nodes with keyset pagination (stable under shared
|
|
13185
|
+
* timestamps and light concurrent writes), transacts per page, skips
|
|
13186
|
+
* kinds with no searchable fields, and cleans up stale rows for
|
|
13187
|
+
* soft-deleted nodes. Corrupt or non-object `props` are counted in
|
|
13188
|
+
* `skipped` with their node IDs surfaced via `skippedIds` so operators
|
|
13189
|
+
* can investigate. Concurrent hard-deletes between page fetches can
|
|
13190
|
+
* be missed by a single pass — run during a maintenance window for
|
|
13191
|
+
* full consistency.
|
|
13192
|
+
*/
|
|
13193
|
+
async rebuildFulltext(nodeKind, options = {}) {
|
|
13194
|
+
return rebuildFulltextIndex(
|
|
13195
|
+
{
|
|
13196
|
+
graphId: this.#context.graphId,
|
|
13197
|
+
backend: this.#context.backend,
|
|
13198
|
+
registry: this.#context.registry
|
|
13199
|
+
},
|
|
13200
|
+
nodeKind,
|
|
13201
|
+
options
|
|
13202
|
+
);
|
|
13203
|
+
}
|
|
13204
|
+
};
|
|
13205
|
+
|
|
11977
13206
|
// src/store/store.ts
|
|
11978
13207
|
var Store = class {
|
|
11979
13208
|
#graph;
|
|
@@ -11985,6 +13214,7 @@ var Store = class {
|
|
|
11985
13214
|
#nodeCollections;
|
|
11986
13215
|
#edgeCollections;
|
|
11987
13216
|
#algorithms;
|
|
13217
|
+
#search;
|
|
11988
13218
|
constructor(graph, backend, options) {
|
|
11989
13219
|
this.#graph = graph;
|
|
11990
13220
|
this.#backend = backend;
|
|
@@ -12233,6 +13463,44 @@ var Store = class {
|
|
|
12233
13463
|
query() {
|
|
12234
13464
|
return this.#createQueryForBackend(this.#backend);
|
|
12235
13465
|
}
|
|
13466
|
+
// === Search ===
|
|
13467
|
+
/**
|
|
13468
|
+
* Search-related operations (fulltext, hybrid, and rebuild).
|
|
13469
|
+
*
|
|
13470
|
+
* All search methods live under this facade to keep the top-level
|
|
13471
|
+
* Store API focused on CRUD + graph traversal. The facade is
|
|
13472
|
+
* lazy-initialized and cached for the lifetime of the store.
|
|
13473
|
+
*
|
|
13474
|
+
* @example
|
|
13475
|
+
* ```typescript
|
|
13476
|
+
* // Fulltext
|
|
13477
|
+
* const hits = await store.search.fulltext("Document", {
|
|
13478
|
+
* query: "climate warming",
|
|
13479
|
+
* limit: 10,
|
|
13480
|
+
* includeSnippets: true,
|
|
13481
|
+
* });
|
|
13482
|
+
*
|
|
13483
|
+
* // Hybrid (vector + fulltext fused with RRF)
|
|
13484
|
+
* const ranked = await store.search.hybrid("Document", {
|
|
13485
|
+
* limit: 10,
|
|
13486
|
+
* vector: { fieldPath: "embedding", queryEmbedding: vec },
|
|
13487
|
+
* fulltext: { query: "climate warming" },
|
|
13488
|
+
* });
|
|
13489
|
+
*
|
|
13490
|
+
* // Rebuild index after schema change
|
|
13491
|
+
* const stats = await store.search.rebuildFulltext();
|
|
13492
|
+
* ```
|
|
13493
|
+
*/
|
|
13494
|
+
get search() {
|
|
13495
|
+
if (this.#search === void 0) {
|
|
13496
|
+
this.#search = new StoreSearch({
|
|
13497
|
+
graphId: this.graphId,
|
|
13498
|
+
backend: this.#backend,
|
|
13499
|
+
registry: this.#registry
|
|
13500
|
+
});
|
|
13501
|
+
}
|
|
13502
|
+
return this.#search;
|
|
13503
|
+
}
|
|
12236
13504
|
// === Batch Query Execution ===
|
|
12237
13505
|
/**
|
|
12238
13506
|
* Executes multiple queries over a single connection with snapshot consistency.
|
|
@@ -12306,7 +13574,7 @@ var Store = class {
|
|
|
12306
13574
|
graphId: this.graphId,
|
|
12307
13575
|
rootId,
|
|
12308
13576
|
backend: this.#backend,
|
|
12309
|
-
dialect:
|
|
13577
|
+
dialect: chunk3JK66E3I_cjs.getDialect(this.#backend.dialect),
|
|
12310
13578
|
schema: this.#schema,
|
|
12311
13579
|
options
|
|
12312
13580
|
});
|
|
@@ -12377,6 +13645,7 @@ var Store = class {
|
|
|
12377
13645
|
this.#nodeCollections = void 0;
|
|
12378
13646
|
this.#edgeCollections = void 0;
|
|
12379
13647
|
this.#algorithms = void 0;
|
|
13648
|
+
this.#search = void 0;
|
|
12380
13649
|
}
|
|
12381
13650
|
// === Lifecycle ===
|
|
12382
13651
|
/**
|
|
@@ -12446,7 +13715,7 @@ var Store = class {
|
|
|
12446
13715
|
// === Internal: Temporal Filtering ===
|
|
12447
13716
|
#matchesTemporalMode(row, options) {
|
|
12448
13717
|
const mode = options?.temporalMode ?? this.#graph.defaults.temporalMode;
|
|
12449
|
-
const asOf = options?.asOf ??
|
|
13718
|
+
const asOf = options?.asOf ?? chunkWRWVWKQL_cjs.nowIso();
|
|
12450
13719
|
switch (mode) {
|
|
12451
13720
|
case "current":
|
|
12452
13721
|
case "asOf": {
|
|
@@ -12479,41 +13748,41 @@ function createStore(graph, backend, options) {
|
|
|
12479
13748
|
}
|
|
12480
13749
|
async function createStoreWithSchema(graph, backend, options) {
|
|
12481
13750
|
const store = createStore(graph, backend, options);
|
|
12482
|
-
const result = await
|
|
13751
|
+
const result = await chunkHRNQ3DVJ_cjs.ensureSchema(backend, graph, options);
|
|
12483
13752
|
return [store, result];
|
|
12484
13753
|
}
|
|
12485
13754
|
|
|
12486
13755
|
Object.defineProperty(exports, "isMetaEdge", {
|
|
12487
13756
|
enumerable: true,
|
|
12488
|
-
get: function () { return
|
|
13757
|
+
get: function () { return chunkHRNQ3DVJ_cjs.isMetaEdge; }
|
|
12489
13758
|
});
|
|
12490
13759
|
Object.defineProperty(exports, "defineGraph", {
|
|
12491
13760
|
enumerable: true,
|
|
12492
|
-
get: function () { return
|
|
13761
|
+
get: function () { return chunkWRWVWKQL_cjs.defineGraph; }
|
|
12493
13762
|
});
|
|
12494
13763
|
Object.defineProperty(exports, "getEdgeKinds", {
|
|
12495
13764
|
enumerable: true,
|
|
12496
|
-
get: function () { return
|
|
13765
|
+
get: function () { return chunkWRWVWKQL_cjs.getEdgeKinds; }
|
|
12497
13766
|
});
|
|
12498
13767
|
Object.defineProperty(exports, "getNodeKinds", {
|
|
12499
13768
|
enumerable: true,
|
|
12500
|
-
get: function () { return
|
|
13769
|
+
get: function () { return chunkWRWVWKQL_cjs.getNodeKinds; }
|
|
12501
13770
|
});
|
|
12502
13771
|
Object.defineProperty(exports, "isEdgeType", {
|
|
12503
13772
|
enumerable: true,
|
|
12504
|
-
get: function () { return
|
|
13773
|
+
get: function () { return chunkWRWVWKQL_cjs.isEdgeType; }
|
|
12505
13774
|
});
|
|
12506
13775
|
Object.defineProperty(exports, "isEdgeTypeWithEndpoints", {
|
|
12507
13776
|
enumerable: true,
|
|
12508
|
-
get: function () { return
|
|
13777
|
+
get: function () { return chunkWRWVWKQL_cjs.isEdgeTypeWithEndpoints; }
|
|
12509
13778
|
});
|
|
12510
13779
|
Object.defineProperty(exports, "isGraphDef", {
|
|
12511
13780
|
enumerable: true,
|
|
12512
|
-
get: function () { return
|
|
13781
|
+
get: function () { return chunkWRWVWKQL_cjs.isGraphDef; }
|
|
12513
13782
|
});
|
|
12514
13783
|
Object.defineProperty(exports, "isNodeType", {
|
|
12515
13784
|
enumerable: true,
|
|
12516
|
-
get: function () { return
|
|
13785
|
+
get: function () { return chunkWRWVWKQL_cjs.isNodeType; }
|
|
12517
13786
|
});
|
|
12518
13787
|
Object.defineProperty(exports, "BackendDisposedError", {
|
|
12519
13788
|
enumerable: true,
|
|
@@ -12615,37 +13884,61 @@ Object.defineProperty(exports, "isUserRecoverable", {
|
|
|
12615
13884
|
enumerable: true,
|
|
12616
13885
|
get: function () { return chunkO5PST6TB_cjs.isUserRecoverable; }
|
|
12617
13886
|
});
|
|
13887
|
+
Object.defineProperty(exports, "fts5Strategy", {
|
|
13888
|
+
enumerable: true,
|
|
13889
|
+
get: function () { return chunk3JK66E3I_cjs.fts5Strategy; }
|
|
13890
|
+
});
|
|
13891
|
+
Object.defineProperty(exports, "tsvectorStrategy", {
|
|
13892
|
+
enumerable: true,
|
|
13893
|
+
get: function () { return chunk3JK66E3I_cjs.tsvectorStrategy; }
|
|
13894
|
+
});
|
|
13895
|
+
Object.defineProperty(exports, "DEFAULT_SEARCHABLE_LANGUAGE", {
|
|
13896
|
+
enumerable: true,
|
|
13897
|
+
get: function () { return chunkUVZHTBZ5_cjs.DEFAULT_SEARCHABLE_LANGUAGE; }
|
|
13898
|
+
});
|
|
12618
13899
|
Object.defineProperty(exports, "MAX_JSON_POINTER_DEPTH", {
|
|
12619
13900
|
enumerable: true,
|
|
12620
|
-
get: function () { return
|
|
13901
|
+
get: function () { return chunkUVZHTBZ5_cjs.MAX_JSON_POINTER_DEPTH; }
|
|
12621
13902
|
});
|
|
12622
13903
|
Object.defineProperty(exports, "embedding", {
|
|
12623
13904
|
enumerable: true,
|
|
12624
|
-
get: function () { return
|
|
13905
|
+
get: function () { return chunkUVZHTBZ5_cjs.embedding; }
|
|
12625
13906
|
});
|
|
12626
13907
|
Object.defineProperty(exports, "getEmbeddingDimensions", {
|
|
12627
13908
|
enumerable: true,
|
|
12628
|
-
get: function () { return
|
|
13909
|
+
get: function () { return chunkUVZHTBZ5_cjs.getEmbeddingDimensions; }
|
|
13910
|
+
});
|
|
13911
|
+
Object.defineProperty(exports, "getSearchableMetadata", {
|
|
13912
|
+
enumerable: true,
|
|
13913
|
+
get: function () { return chunkUVZHTBZ5_cjs.getSearchableMetadata; }
|
|
12629
13914
|
});
|
|
12630
13915
|
Object.defineProperty(exports, "isEmbeddingSchema", {
|
|
12631
13916
|
enumerable: true,
|
|
12632
|
-
get: function () { return
|
|
13917
|
+
get: function () { return chunkUVZHTBZ5_cjs.isEmbeddingSchema; }
|
|
13918
|
+
});
|
|
13919
|
+
Object.defineProperty(exports, "isSearchableSchema", {
|
|
13920
|
+
enumerable: true,
|
|
13921
|
+
get: function () { return chunkUVZHTBZ5_cjs.isSearchableSchema; }
|
|
12633
13922
|
});
|
|
12634
13923
|
Object.defineProperty(exports, "joinJsonPointers", {
|
|
12635
13924
|
enumerable: true,
|
|
12636
|
-
get: function () { return
|
|
13925
|
+
get: function () { return chunkUVZHTBZ5_cjs.joinJsonPointers; }
|
|
12637
13926
|
});
|
|
12638
13927
|
Object.defineProperty(exports, "jsonPointer", {
|
|
12639
13928
|
enumerable: true,
|
|
12640
|
-
get: function () { return
|
|
13929
|
+
get: function () { return chunkUVZHTBZ5_cjs.jsonPointer; }
|
|
12641
13930
|
});
|
|
12642
13931
|
Object.defineProperty(exports, "normalizeJsonPointer", {
|
|
12643
13932
|
enumerable: true,
|
|
12644
|
-
get: function () { return
|
|
13933
|
+
get: function () { return chunkUVZHTBZ5_cjs.normalizeJsonPointer; }
|
|
12645
13934
|
});
|
|
12646
13935
|
Object.defineProperty(exports, "parseJsonPointer", {
|
|
12647
13936
|
enumerable: true,
|
|
12648
|
-
get: function () { return
|
|
13937
|
+
get: function () { return chunkUVZHTBZ5_cjs.parseJsonPointer; }
|
|
13938
|
+
});
|
|
13939
|
+
Object.defineProperty(exports, "searchable", {
|
|
13940
|
+
enumerable: true,
|
|
13941
|
+
get: function () { return chunkUVZHTBZ5_cjs.searchable; }
|
|
12649
13942
|
});
|
|
12650
13943
|
exports.DEFAULT_SQL_SCHEMA = DEFAULT_SQL_SCHEMA;
|
|
12651
13944
|
exports.ExecutableAggregateQuery = ExecutableAggregateQuery;
|
|
@@ -12654,6 +13947,7 @@ exports.MAX_EXPLICIT_RECURSIVE_DEPTH = MAX_EXPLICIT_RECURSIVE_DEPTH;
|
|
|
12654
13947
|
exports.MAX_RECURSIVE_DEPTH = MAX_RECURSIVE_DEPTH;
|
|
12655
13948
|
exports.PreparedQuery = PreparedQuery;
|
|
12656
13949
|
exports.QueryBuilder = QueryBuilder;
|
|
13950
|
+
exports.StoreSearch = StoreSearch;
|
|
12657
13951
|
exports.UnionableQuery = UnionableQuery;
|
|
12658
13952
|
exports.avg = avg;
|
|
12659
13953
|
exports.broader = broader;
|
|
@@ -12661,6 +13955,8 @@ exports.composeFragments = composeFragments;
|
|
|
12661
13955
|
exports.core = core;
|
|
12662
13956
|
exports.count = count;
|
|
12663
13957
|
exports.countDistinct = countDistinct;
|
|
13958
|
+
exports.countDistinctEdges = countDistinctEdges;
|
|
13959
|
+
exports.countEdges = countEdges;
|
|
12664
13960
|
exports.createExternalRef = createExternalRef;
|
|
12665
13961
|
exports.createFragment = createFragment;
|
|
12666
13962
|
exports.createQueryBuilder = createQueryBuilder;
|