@nicia-ai/typegraph 0.11.1 → 0.12.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/index.cjs +2370 -1948
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2370 -1949
- package/dist/index.js.map +1 -1
- package/dist/interchange/index.d.cts +1 -1
- package/dist/interchange/index.d.ts +1 -1
- package/dist/profiler/index.d.cts +1 -1
- package/dist/profiler/index.d.ts +1 -1
- package/dist/{store-Cy6gSNqg.d.ts → store-BcnA11lH.d.ts} +150 -8
- package/dist/{store-C01_WsOg.d.cts → store-NEa4EFFD.d.cts} +150 -8
- package/package.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -311,72 +311,6 @@ var core = {
|
|
|
311
311
|
implies
|
|
312
312
|
};
|
|
313
313
|
|
|
314
|
-
// src/query/compiler/passes/recursive.ts
|
|
315
|
-
function runRecursiveTraversalSelectionPass(ast) {
|
|
316
|
-
const variableLengthTraversal = ast.traversals.find(
|
|
317
|
-
(traversal) => traversal.variableLength !== void 0
|
|
318
|
-
);
|
|
319
|
-
if (variableLengthTraversal === void 0) {
|
|
320
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError("No variable-length traversal found");
|
|
321
|
-
}
|
|
322
|
-
if (ast.traversals.length > 1) {
|
|
323
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
324
|
-
"Variable-length traversals with multiple traversals are not yet supported. Please use a single variable-length traversal."
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
return variableLengthTraversal;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// src/query/compiler/passes/runner.ts
|
|
331
|
-
function runCompilerPass(state, pass) {
|
|
332
|
-
const output = pass.execute(state);
|
|
333
|
-
return {
|
|
334
|
-
state: pass.update(state, output)
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
function compileTemporalFilter(options) {
|
|
338
|
-
const { mode, asOf, tableAlias, currentTimestamp } = options;
|
|
339
|
-
const prefix = tableAlias ? drizzleOrm.sql.raw(`${tableAlias}.`) : drizzleOrm.sql.raw("");
|
|
340
|
-
const deletedAt = drizzleOrm.sql`${prefix}deleted_at`;
|
|
341
|
-
const validFrom = drizzleOrm.sql`${prefix}valid_from`;
|
|
342
|
-
const validTo = drizzleOrm.sql`${prefix}valid_to`;
|
|
343
|
-
switch (mode) {
|
|
344
|
-
case "current": {
|
|
345
|
-
const now = currentTimestamp ?? drizzleOrm.sql`CURRENT_TIMESTAMP`;
|
|
346
|
-
return drizzleOrm.sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${now}) AND (${validTo} IS NULL OR ${validTo} > ${now})`;
|
|
347
|
-
}
|
|
348
|
-
case "asOf": {
|
|
349
|
-
const timestamp = asOf;
|
|
350
|
-
return drizzleOrm.sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${timestamp}) AND (${validTo} IS NULL OR ${validTo} > ${timestamp})`;
|
|
351
|
-
}
|
|
352
|
-
case "includeEnded": {
|
|
353
|
-
return drizzleOrm.sql`${deletedAt} IS NULL`;
|
|
354
|
-
}
|
|
355
|
-
case "includeTombstones": {
|
|
356
|
-
return drizzleOrm.sql.raw("1=1");
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
function extractTemporalOptions(ast, tableAlias) {
|
|
361
|
-
return {
|
|
362
|
-
mode: ast.temporalMode.mode,
|
|
363
|
-
asOf: ast.temporalMode.asOf,
|
|
364
|
-
tableAlias
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// src/query/compiler/passes/temporal.ts
|
|
369
|
-
function createTemporalFilterPass(ast, currentTimestamp) {
|
|
370
|
-
return {
|
|
371
|
-
forAlias(tableAlias) {
|
|
372
|
-
return compileTemporalFilter({
|
|
373
|
-
...extractTemporalOptions(ast, tableAlias),
|
|
374
|
-
currentTimestamp
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
|
|
380
314
|
// src/query/subquery-utils.ts
|
|
381
315
|
function normalizeValueType(valueType) {
|
|
382
316
|
if (valueType === void 0 || valueType === "unknown") {
|
|
@@ -1463,1179 +1397,1876 @@ function extractVectorSimilarityPredicates(predicates) {
|
|
|
1463
1397
|
return results;
|
|
1464
1398
|
}
|
|
1465
1399
|
|
|
1466
|
-
// src/query/compiler/
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1400
|
+
// src/query/compiler/predicate-utils.ts
|
|
1401
|
+
var EMPTY_PREDICATES = [];
|
|
1402
|
+
function buildPredicateIndexKey(alias, targetType) {
|
|
1403
|
+
return `${alias}\0${targetType}`;
|
|
1404
|
+
}
|
|
1405
|
+
function resolvePredicateTargetType(predicate2) {
|
|
1406
|
+
return predicate2.targetType === "edge" ? "edge" : "node";
|
|
1407
|
+
}
|
|
1408
|
+
function buildPredicateIndex(ast) {
|
|
1409
|
+
const byAliasAndType = /* @__PURE__ */ new Map();
|
|
1410
|
+
for (const predicate2 of ast.predicates) {
|
|
1411
|
+
const key = buildPredicateIndexKey(
|
|
1412
|
+
predicate2.targetAlias,
|
|
1413
|
+
resolvePredicateTargetType(predicate2)
|
|
1472
1414
|
);
|
|
1415
|
+
const existing = byAliasAndType.get(key);
|
|
1416
|
+
if (existing === void 0) {
|
|
1417
|
+
byAliasAndType.set(key, [predicate2]);
|
|
1418
|
+
} else {
|
|
1419
|
+
existing.push(predicate2);
|
|
1420
|
+
}
|
|
1473
1421
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1422
|
+
return { byAliasAndType };
|
|
1423
|
+
}
|
|
1424
|
+
function getPredicatesForAlias(predicateIndex, alias, targetType) {
|
|
1425
|
+
return predicateIndex.byAliasAndType.get(
|
|
1426
|
+
buildPredicateIndexKey(alias, targetType)
|
|
1427
|
+
) ?? EMPTY_PREDICATES;
|
|
1428
|
+
}
|
|
1429
|
+
function compilePredicateClauses(predicates, predicateContext) {
|
|
1430
|
+
return predicates.map(
|
|
1431
|
+
(predicate2) => compilePredicateExpression(predicate2.expression, predicateContext)
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
function compileKindFilter(column, kinds) {
|
|
1435
|
+
if (kinds.length === 0) {
|
|
1436
|
+
return drizzleOrm.sql`1 = 0`;
|
|
1477
1437
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
1481
|
-
`Vector similarity predicates are not supported for dialect "${dialect.name}"`
|
|
1482
|
-
);
|
|
1438
|
+
if (kinds.length === 1) {
|
|
1439
|
+
return drizzleOrm.sql`${column} = ${kinds[0]}`;
|
|
1483
1440
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1441
|
+
return drizzleOrm.sql`${column} IN (${drizzleOrm.sql.join(
|
|
1442
|
+
kinds.map((kind) => drizzleOrm.sql`${kind}`),
|
|
1443
|
+
drizzleOrm.sql`, `
|
|
1444
|
+
)})`;
|
|
1445
|
+
}
|
|
1446
|
+
function getNodeKindsForAlias(ast, alias) {
|
|
1447
|
+
if (alias === ast.start.alias) {
|
|
1448
|
+
return ast.start.kinds;
|
|
1488
1449
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1450
|
+
for (const traversal of ast.traversals) {
|
|
1451
|
+
if (traversal.nodeAlias === alias) {
|
|
1452
|
+
return traversal.nodeKinds;
|
|
1453
|
+
}
|
|
1493
1454
|
}
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1455
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(`Unknown traversal source alias: ${alias}`);
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// src/query/compiler/emitter/plan-inspector.ts
|
|
1459
|
+
function collectPlanOperations(node, ops) {
|
|
1460
|
+
ops.add(node.op);
|
|
1461
|
+
switch (node.op) {
|
|
1462
|
+
case "aggregate":
|
|
1463
|
+
case "filter":
|
|
1464
|
+
case "join":
|
|
1465
|
+
case "limit_offset":
|
|
1466
|
+
case "project":
|
|
1467
|
+
case "recursive_expand":
|
|
1468
|
+
case "sort":
|
|
1469
|
+
case "vector_knn": {
|
|
1470
|
+
collectPlanOperations(node.input, ops);
|
|
1471
|
+
return;
|
|
1500
1472
|
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1473
|
+
case "set_op": {
|
|
1474
|
+
collectPlanOperations(node.left, ops);
|
|
1475
|
+
collectPlanOperations(node.right, ops);
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
case "scan": {
|
|
1479
|
+
return;
|
|
1505
1480
|
}
|
|
1506
1481
|
}
|
|
1507
|
-
return { vectorPredicate };
|
|
1508
1482
|
}
|
|
1509
|
-
function
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1483
|
+
function findUnaryNodeInProjectChain(rootNode, op) {
|
|
1484
|
+
let currentNode = rootNode.input;
|
|
1485
|
+
for (; ; ) {
|
|
1486
|
+
if (currentNode.op === op) {
|
|
1487
|
+
return currentNode;
|
|
1488
|
+
}
|
|
1489
|
+
switch (currentNode.op) {
|
|
1490
|
+
case "aggregate":
|
|
1491
|
+
case "filter":
|
|
1492
|
+
case "join":
|
|
1493
|
+
case "limit_offset":
|
|
1494
|
+
case "recursive_expand":
|
|
1495
|
+
case "sort":
|
|
1496
|
+
case "vector_knn": {
|
|
1497
|
+
currentNode = currentNode.input;
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
case "project":
|
|
1501
|
+
case "scan":
|
|
1502
|
+
case "set_op": {
|
|
1503
|
+
return void 0;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1515
1506
|
}
|
|
1516
|
-
return Math.min(astLimit, vectorPredicate.limit);
|
|
1517
1507
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1508
|
+
function inspectProjectPlan(logicalPlan) {
|
|
1509
|
+
if (logicalPlan.root.op !== "project") {
|
|
1510
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1511
|
+
`SQL emitter expected logical plan root to be "project", got "${logicalPlan.root.op}"`,
|
|
1512
|
+
{ component: "plan-inspector" }
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
const operations = /* @__PURE__ */ new Set();
|
|
1516
|
+
collectPlanOperations(logicalPlan.root, operations);
|
|
1517
|
+
const limitOffsetNode = findUnaryNodeInProjectChain(
|
|
1518
|
+
logicalPlan.root,
|
|
1519
|
+
"limit_offset"
|
|
1520
|
+
);
|
|
1521
|
+
const sortNode = findUnaryNodeInProjectChain(
|
|
1522
|
+
logicalPlan.root,
|
|
1523
|
+
"sort"
|
|
1524
|
+
);
|
|
1525
|
+
return {
|
|
1526
|
+
hasAggregate: operations.has("aggregate"),
|
|
1527
|
+
hasLimitOffset: operations.has("limit_offset"),
|
|
1528
|
+
hasRecursiveExpand: operations.has("recursive_expand"),
|
|
1529
|
+
hasSetOperation: operations.has("set_op"),
|
|
1530
|
+
hasSort: operations.has("sort"),
|
|
1531
|
+
hasVectorKnn: operations.has("vector_knn"),
|
|
1532
|
+
limitOffsetNode,
|
|
1533
|
+
rootProjectNode: logicalPlan.root,
|
|
1534
|
+
sortNode
|
|
1525
1535
|
};
|
|
1526
1536
|
}
|
|
1527
|
-
function
|
|
1528
|
-
const
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1537
|
+
function inspectStandardProjectPlan(logicalPlan) {
|
|
1538
|
+
const shape = inspectProjectPlan(logicalPlan);
|
|
1539
|
+
if (shape.hasSetOperation) {
|
|
1540
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1541
|
+
'Standard SQL emitter does not support plans containing "set_op" nodes',
|
|
1542
|
+
{ component: "plan-inspector" }
|
|
1543
|
+
);
|
|
1533
1544
|
}
|
|
1534
|
-
|
|
1545
|
+
if (shape.hasRecursiveExpand) {
|
|
1546
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1547
|
+
'Standard SQL emitter does not support plans containing "recursive_expand" nodes',
|
|
1548
|
+
{ component: "plan-inspector" }
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
1551
|
+
return shape;
|
|
1535
1552
|
}
|
|
1536
|
-
function
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1553
|
+
function inspectRecursiveProjectPlan(logicalPlan) {
|
|
1554
|
+
const shape = inspectProjectPlan(logicalPlan);
|
|
1555
|
+
if (!shape.hasRecursiveExpand) {
|
|
1556
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1557
|
+
'Recursive SQL emitter expected logical plan to contain a "recursive_expand" node',
|
|
1558
|
+
{ component: "plan-inspector" }
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
if (shape.hasSetOperation) {
|
|
1562
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1563
|
+
'Recursive SQL emitter does not support plans containing "set_op" nodes',
|
|
1564
|
+
{ component: "plan-inspector" }
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
return shape;
|
|
1541
1568
|
}
|
|
1542
|
-
function
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1569
|
+
function findTopLevelLimitOffsetNode(rootNode) {
|
|
1570
|
+
let currentNode = rootNode;
|
|
1571
|
+
for (; ; ) {
|
|
1572
|
+
if (currentNode.op === "limit_offset") {
|
|
1573
|
+
return currentNode;
|
|
1574
|
+
}
|
|
1575
|
+
switch (currentNode.op) {
|
|
1576
|
+
case "aggregate":
|
|
1577
|
+
case "filter":
|
|
1578
|
+
case "join":
|
|
1579
|
+
case "project":
|
|
1580
|
+
case "recursive_expand":
|
|
1581
|
+
case "sort":
|
|
1582
|
+
case "vector_knn": {
|
|
1583
|
+
currentNode = currentNode.input;
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
case "scan":
|
|
1587
|
+
case "set_op": {
|
|
1588
|
+
return void 0;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
function findTopLevelSortNode(rootNode) {
|
|
1594
|
+
let currentNode = rootNode;
|
|
1595
|
+
for (; ; ) {
|
|
1596
|
+
if (currentNode.op === "sort") {
|
|
1597
|
+
return currentNode;
|
|
1598
|
+
}
|
|
1599
|
+
switch (currentNode.op) {
|
|
1600
|
+
case "aggregate":
|
|
1601
|
+
case "filter":
|
|
1602
|
+
case "join":
|
|
1603
|
+
case "limit_offset":
|
|
1604
|
+
case "project":
|
|
1605
|
+
case "recursive_expand":
|
|
1606
|
+
case "vector_knn": {
|
|
1607
|
+
currentNode = currentNode.input;
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
case "scan":
|
|
1611
|
+
case "set_op": {
|
|
1612
|
+
return void 0;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
function inspectSetOperationPlan(logicalPlan) {
|
|
1618
|
+
const operations = /* @__PURE__ */ new Set();
|
|
1619
|
+
collectPlanOperations(logicalPlan.root, operations);
|
|
1620
|
+
if (!operations.has("set_op")) {
|
|
1621
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1622
|
+
'Set-operation SQL emitter expected logical plan to contain a "set_op" node',
|
|
1623
|
+
{ component: "plan-inspector" }
|
|
1624
|
+
);
|
|
1546
1625
|
}
|
|
1626
|
+
const limitOffsetNode = findTopLevelLimitOffsetNode(logicalPlan.root);
|
|
1627
|
+
const sortNode = findTopLevelSortNode(logicalPlan.root);
|
|
1547
1628
|
return {
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
predicates: aliasPredicates.map((predicate2) => predicate2.expression)
|
|
1629
|
+
hasLimitOffset: limitOffsetNode !== void 0,
|
|
1630
|
+
hasSetOperation: true,
|
|
1631
|
+
hasSort: sortNode !== void 0,
|
|
1632
|
+
limitOffsetNode,
|
|
1633
|
+
sortNode
|
|
1554
1634
|
};
|
|
1555
1635
|
}
|
|
1556
|
-
function
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
id: nextPlanNodeId(),
|
|
1564
|
-
input: node,
|
|
1565
|
-
op: "aggregate"
|
|
1566
|
-
};
|
|
1567
|
-
node = ast.having === void 0 ? aggregateNode : { ...aggregateNode, having: ast.having };
|
|
1636
|
+
function assertRecursiveEmitterClauseAlignment(logicalPlan, input) {
|
|
1637
|
+
const planShape = inspectRecursiveProjectPlan(logicalPlan);
|
|
1638
|
+
if (planShape.hasSort && input.orderBy === void 0) {
|
|
1639
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1640
|
+
"Recursive SQL emitter expected ORDER BY clause for plan containing a sort node",
|
|
1641
|
+
{ component: "recursive-emitter" }
|
|
1642
|
+
);
|
|
1568
1643
|
}
|
|
1569
|
-
if (
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
orderBy: ast.orderBy
|
|
1575
|
-
};
|
|
1644
|
+
if (!planShape.hasSort && input.orderBy !== void 0) {
|
|
1645
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1646
|
+
"Recursive SQL emitter received ORDER BY clause for a plan without sort nodes",
|
|
1647
|
+
{ component: "recursive-emitter" }
|
|
1648
|
+
);
|
|
1576
1649
|
}
|
|
1577
|
-
if (
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1650
|
+
if (planShape.hasLimitOffset && input.limitOffset === void 0) {
|
|
1651
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1652
|
+
"Recursive SQL emitter expected LIMIT/OFFSET clause for plan containing a limit_offset node",
|
|
1653
|
+
{ component: "recursive-emitter" }
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
if (!planShape.hasLimitOffset && input.limitOffset !== void 0) {
|
|
1657
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1658
|
+
"Recursive SQL emitter received LIMIT/OFFSET clause for a plan without limit_offset nodes",
|
|
1659
|
+
{ component: "recursive-emitter" }
|
|
1660
|
+
);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
function emitRecursiveQuerySql(input) {
|
|
1664
|
+
assertRecursiveEmitterClauseAlignment(input.logicalPlan, input);
|
|
1665
|
+
const parts = [
|
|
1666
|
+
drizzleOrm.sql`WITH RECURSIVE`,
|
|
1667
|
+
input.recursiveCte,
|
|
1668
|
+
drizzleOrm.sql`SELECT ${input.projection}`,
|
|
1669
|
+
drizzleOrm.sql`FROM recursive_cte`,
|
|
1670
|
+
input.depthFilter
|
|
1671
|
+
];
|
|
1672
|
+
if (input.orderBy !== void 0) {
|
|
1673
|
+
parts.push(input.orderBy);
|
|
1674
|
+
}
|
|
1675
|
+
if (input.limitOffset !== void 0) {
|
|
1676
|
+
parts.push(input.limitOffset);
|
|
1677
|
+
}
|
|
1678
|
+
return drizzleOrm.sql.join(parts, drizzleOrm.sql` `);
|
|
1679
|
+
}
|
|
1680
|
+
function assertSetOperationEmitterClauseAlignment(logicalPlan, suffixClauses) {
|
|
1681
|
+
const shape = inspectSetOperationPlan(logicalPlan);
|
|
1682
|
+
const hasSuffixClauses = suffixClauses !== void 0 && suffixClauses.length > 0;
|
|
1683
|
+
if (!shape.hasSort && !shape.hasLimitOffset && hasSuffixClauses) {
|
|
1684
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1685
|
+
"Set-operation SQL emitter received suffix clauses for a plan without top-level sort or limit_offset nodes",
|
|
1686
|
+
{ component: "set-operation-emitter" }
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
if (!hasSuffixClauses) {
|
|
1690
|
+
if (shape.hasSort || shape.hasLimitOffset) {
|
|
1596
1691
|
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1597
|
-
"
|
|
1692
|
+
"Set-operation SQL emitter expected suffix clauses for plan containing top-level sort or limit_offset nodes",
|
|
1693
|
+
{ component: "set-operation-emitter" }
|
|
1598
1694
|
);
|
|
1599
1695
|
}
|
|
1696
|
+
return;
|
|
1600
1697
|
}
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
return collapsedTraversalCteAlias === void 0 ? projectNodeBase : {
|
|
1608
|
-
...projectNodeBase,
|
|
1609
|
-
collapsedTraversalAlias: collapsedTraversalCteAlias
|
|
1610
|
-
};
|
|
1611
|
-
}
|
|
1612
|
-
function lowerStandardQueryToLogicalPlanNode(input) {
|
|
1613
|
-
const { ast, nextPlanNodeId } = input;
|
|
1614
|
-
let currentNode = {
|
|
1615
|
-
alias: ast.start.alias,
|
|
1616
|
-
graphId: input.graphId,
|
|
1617
|
-
id: nextPlanNodeId(),
|
|
1618
|
-
kinds: ast.start.kinds,
|
|
1619
|
-
op: "scan",
|
|
1620
|
-
source: "nodes"
|
|
1621
|
-
};
|
|
1622
|
-
currentNode = wrapWithAliasFilterNode(
|
|
1623
|
-
currentNode,
|
|
1624
|
-
ast,
|
|
1625
|
-
ast.start.alias,
|
|
1626
|
-
"node",
|
|
1627
|
-
nextPlanNodeId
|
|
1628
|
-
);
|
|
1629
|
-
for (const traversal of ast.traversals) {
|
|
1630
|
-
currentNode = {
|
|
1631
|
-
direction: traversal.direction,
|
|
1632
|
-
edgeAlias: traversal.edgeAlias,
|
|
1633
|
-
edgeKinds: traversal.edgeKinds,
|
|
1634
|
-
id: nextPlanNodeId(),
|
|
1635
|
-
input: currentNode,
|
|
1636
|
-
inverseEdgeKinds: traversal.inverseEdgeKinds ?? [],
|
|
1637
|
-
joinFromAlias: traversal.joinFromAlias,
|
|
1638
|
-
joinType: traversal.optional ? "left" : "inner",
|
|
1639
|
-
nodeAlias: traversal.nodeAlias,
|
|
1640
|
-
nodeKinds: traversal.nodeKinds,
|
|
1641
|
-
op: "join"
|
|
1642
|
-
};
|
|
1643
|
-
currentNode = wrapWithAliasFilterNode(
|
|
1644
|
-
currentNode,
|
|
1645
|
-
ast,
|
|
1646
|
-
traversal.edgeAlias,
|
|
1647
|
-
"edge",
|
|
1648
|
-
nextPlanNodeId
|
|
1649
|
-
);
|
|
1650
|
-
currentNode = wrapWithAliasFilterNode(
|
|
1651
|
-
currentNode,
|
|
1652
|
-
ast,
|
|
1653
|
-
traversal.nodeAlias,
|
|
1654
|
-
"node",
|
|
1655
|
-
nextPlanNodeId
|
|
1698
|
+
const limitOffsetClauseCount = shape.limitOffsetNode === void 0 ? 0 : (shape.limitOffsetNode.limit === void 0 ? 0 : 1) + (shape.limitOffsetNode.offset === void 0 ? 0 : 1);
|
|
1699
|
+
const expectedClauseCount = (shape.sortNode === void 0 ? 0 : 1) + limitOffsetClauseCount;
|
|
1700
|
+
if (suffixClauses.length !== expectedClauseCount) {
|
|
1701
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1702
|
+
`Set-operation SQL emitter expected ${String(expectedClauseCount)} top-level suffix clause(s) from logical plan, got ${String(suffixClauses.length)}`,
|
|
1703
|
+
{ component: "set-operation-emitter" }
|
|
1656
1704
|
);
|
|
1657
1705
|
}
|
|
1658
|
-
if (input.vectorPredicate !== void 0) {
|
|
1659
|
-
currentNode = {
|
|
1660
|
-
id: nextPlanNodeId(),
|
|
1661
|
-
input: currentNode,
|
|
1662
|
-
op: "vector_knn",
|
|
1663
|
-
predicate: input.vectorPredicate
|
|
1664
|
-
};
|
|
1665
|
-
}
|
|
1666
|
-
return appendAggregateSortLimitAndProjectNodes(
|
|
1667
|
-
currentNode,
|
|
1668
|
-
ast,
|
|
1669
|
-
nextPlanNodeId,
|
|
1670
|
-
input.effectiveLimit,
|
|
1671
|
-
input.collapsedTraversalCteAlias
|
|
1672
|
-
);
|
|
1673
1706
|
}
|
|
1674
|
-
function
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
alias: ast.start.alias,
|
|
1679
|
-
graphId: input.graphId,
|
|
1680
|
-
id: nextPlanNodeId(),
|
|
1681
|
-
kinds: ast.start.kinds,
|
|
1682
|
-
op: "scan",
|
|
1683
|
-
source: "nodes"
|
|
1684
|
-
};
|
|
1685
|
-
currentNode = wrapWithAliasFilterNode(
|
|
1686
|
-
currentNode,
|
|
1687
|
-
ast,
|
|
1688
|
-
ast.start.alias,
|
|
1689
|
-
"node",
|
|
1690
|
-
nextPlanNodeId
|
|
1691
|
-
);
|
|
1692
|
-
currentNode = {
|
|
1693
|
-
edgeAlias: traversal.edgeAlias,
|
|
1694
|
-
edgeKinds: traversal.edgeKinds,
|
|
1695
|
-
id: nextPlanNodeId(),
|
|
1696
|
-
input: currentNode,
|
|
1697
|
-
inverseEdgeKinds: traversal.inverseEdgeKinds ?? [],
|
|
1698
|
-
nodeAlias: traversal.nodeAlias,
|
|
1699
|
-
nodeKinds: traversal.nodeKinds,
|
|
1700
|
-
op: "recursive_expand",
|
|
1701
|
-
traversal: traversal.variableLength
|
|
1702
|
-
};
|
|
1703
|
-
currentNode = wrapWithAliasFilterNode(
|
|
1704
|
-
currentNode,
|
|
1705
|
-
ast,
|
|
1706
|
-
traversal.edgeAlias,
|
|
1707
|
-
"edge",
|
|
1708
|
-
nextPlanNodeId
|
|
1709
|
-
);
|
|
1710
|
-
currentNode = wrapWithAliasFilterNode(
|
|
1711
|
-
currentNode,
|
|
1712
|
-
ast,
|
|
1713
|
-
traversal.nodeAlias,
|
|
1714
|
-
"node",
|
|
1715
|
-
nextPlanNodeId
|
|
1716
|
-
);
|
|
1717
|
-
return appendAggregateSortLimitAndProjectNodes(
|
|
1718
|
-
currentNode,
|
|
1719
|
-
ast,
|
|
1720
|
-
nextPlanNodeId,
|
|
1721
|
-
ast.limit
|
|
1707
|
+
function emitSetOperationQuerySql(input) {
|
|
1708
|
+
assertSetOperationEmitterClauseAlignment(
|
|
1709
|
+
input.logicalPlan,
|
|
1710
|
+
input.suffixClauses
|
|
1722
1711
|
);
|
|
1712
|
+
const parts = [];
|
|
1713
|
+
if (input.ctes !== void 0 && input.ctes.length > 0) {
|
|
1714
|
+
parts.push(drizzleOrm.sql`WITH ${drizzleOrm.sql.join([...input.ctes], drizzleOrm.sql`, `)}`);
|
|
1715
|
+
}
|
|
1716
|
+
parts.push(input.baseQuery);
|
|
1717
|
+
if (input.suffixClauses !== void 0 && input.suffixClauses.length > 0) {
|
|
1718
|
+
parts.push(...input.suffixClauses);
|
|
1719
|
+
}
|
|
1720
|
+
return drizzleOrm.sql.join(parts, drizzleOrm.sql` `);
|
|
1723
1721
|
}
|
|
1724
|
-
function
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
nextPlanNodeId
|
|
1722
|
+
function assertStandardEmitterClauseAlignment(logicalPlan, input) {
|
|
1723
|
+
const planShape = inspectStandardProjectPlan(logicalPlan);
|
|
1724
|
+
if (input.groupBy !== void 0 && !planShape.hasAggregate) {
|
|
1725
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1726
|
+
"Standard SQL emitter received GROUP BY clause for a plan without aggregate nodes",
|
|
1727
|
+
{ component: "standard-emitter" }
|
|
1731
1728
|
);
|
|
1732
1729
|
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
ast: query,
|
|
1739
|
-
graphId,
|
|
1740
|
-
nextPlanNodeId
|
|
1741
|
-
});
|
|
1730
|
+
if (input.having !== void 0 && !planShape.hasAggregate) {
|
|
1731
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1732
|
+
"Standard SQL emitter received HAVING clause for a plan without aggregate nodes",
|
|
1733
|
+
{ component: "standard-emitter" }
|
|
1734
|
+
);
|
|
1742
1735
|
}
|
|
1743
|
-
const
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
ast: query,
|
|
1750
|
-
graphId,
|
|
1751
|
-
nextPlanNodeId,
|
|
1752
|
-
...effectiveLimit === void 0 ? {} : { effectiveLimit },
|
|
1753
|
-
...vectorPredicate === void 0 ? {} : { vectorPredicate }
|
|
1754
|
-
};
|
|
1755
|
-
return lowerStandardQueryToLogicalPlanNode(loweringInput);
|
|
1756
|
-
}
|
|
1757
|
-
function lowerSetOperationToLogicalPlanNode(op, graphId, dialect, nextPlanNodeId) {
|
|
1758
|
-
let currentNode = {
|
|
1759
|
-
id: nextPlanNodeId(),
|
|
1760
|
-
left: lowerComposableQueryToLogicalPlanNode(
|
|
1761
|
-
op.left,
|
|
1762
|
-
dialect,
|
|
1763
|
-
graphId,
|
|
1764
|
-
nextPlanNodeId
|
|
1765
|
-
),
|
|
1766
|
-
op: "set_op",
|
|
1767
|
-
operator: op.operator,
|
|
1768
|
-
right: lowerComposableQueryToLogicalPlanNode(
|
|
1769
|
-
op.right,
|
|
1770
|
-
dialect,
|
|
1771
|
-
graphId,
|
|
1772
|
-
nextPlanNodeId
|
|
1773
|
-
)
|
|
1774
|
-
};
|
|
1775
|
-
if (op.orderBy !== void 0 && op.orderBy.length > 0) {
|
|
1776
|
-
currentNode = {
|
|
1777
|
-
id: nextPlanNodeId(),
|
|
1778
|
-
input: currentNode,
|
|
1779
|
-
op: "sort",
|
|
1780
|
-
orderBy: op.orderBy
|
|
1781
|
-
};
|
|
1736
|
+
const expectsOrderBy = planShape.hasSort || planShape.hasVectorKnn;
|
|
1737
|
+
if (expectsOrderBy && input.orderBy === void 0) {
|
|
1738
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1739
|
+
"Standard SQL emitter expected ORDER BY clause for plan containing a sort or vector_knn node",
|
|
1740
|
+
{ component: "standard-emitter" }
|
|
1741
|
+
);
|
|
1782
1742
|
}
|
|
1783
|
-
if (
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1743
|
+
if (!expectsOrderBy && input.orderBy !== void 0) {
|
|
1744
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1745
|
+
"Standard SQL emitter received ORDER BY clause for a plan without sort or vector_knn nodes",
|
|
1746
|
+
{ component: "standard-emitter" }
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
if (planShape.hasLimitOffset && input.limitOffset === void 0) {
|
|
1750
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1751
|
+
"Standard SQL emitter expected LIMIT/OFFSET clause for plan containing a limit_offset node",
|
|
1752
|
+
{ component: "standard-emitter" }
|
|
1753
|
+
);
|
|
1754
|
+
}
|
|
1755
|
+
if (!planShape.hasLimitOffset && input.limitOffset !== void 0) {
|
|
1756
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1757
|
+
"Standard SQL emitter received LIMIT/OFFSET clause for a plan without limit_offset nodes",
|
|
1758
|
+
{ component: "standard-emitter" }
|
|
1759
|
+
);
|
|
1796
1760
|
}
|
|
1797
|
-
return currentNode;
|
|
1798
|
-
}
|
|
1799
|
-
function lowerStandardQueryToLogicalPlan(input) {
|
|
1800
|
-
const nextPlanNodeId = createPlanNodeIdFactory();
|
|
1801
|
-
return {
|
|
1802
|
-
metadata: {
|
|
1803
|
-
dialect: input.dialect,
|
|
1804
|
-
graphId: input.graphId
|
|
1805
|
-
},
|
|
1806
|
-
root: lowerStandardQueryToLogicalPlanNode({
|
|
1807
|
-
...input,
|
|
1808
|
-
nextPlanNodeId
|
|
1809
|
-
})
|
|
1810
|
-
};
|
|
1811
|
-
}
|
|
1812
|
-
function lowerRecursiveQueryToLogicalPlan(input) {
|
|
1813
|
-
const nextPlanNodeId = createPlanNodeIdFactory();
|
|
1814
|
-
return {
|
|
1815
|
-
metadata: {
|
|
1816
|
-
dialect: input.dialect,
|
|
1817
|
-
graphId: input.graphId
|
|
1818
|
-
},
|
|
1819
|
-
root: lowerRecursiveQueryToLogicalPlanNode({
|
|
1820
|
-
...input,
|
|
1821
|
-
nextPlanNodeId
|
|
1822
|
-
})
|
|
1823
|
-
};
|
|
1824
1761
|
}
|
|
1825
|
-
function
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1762
|
+
function emitStandardQuerySql(input) {
|
|
1763
|
+
assertStandardEmitterClauseAlignment(input.logicalPlan, input);
|
|
1764
|
+
const parts = [];
|
|
1765
|
+
if (input.ctes.length > 0) {
|
|
1766
|
+
parts.push(drizzleOrm.sql`WITH ${drizzleOrm.sql.join([...input.ctes], drizzleOrm.sql`, `)}`);
|
|
1767
|
+
}
|
|
1768
|
+
parts.push(drizzleOrm.sql`SELECT ${input.projection}`, input.fromClause);
|
|
1769
|
+
if (input.groupBy !== void 0) {
|
|
1770
|
+
parts.push(input.groupBy);
|
|
1771
|
+
}
|
|
1772
|
+
if (input.having !== void 0) {
|
|
1773
|
+
parts.push(input.having);
|
|
1774
|
+
}
|
|
1775
|
+
if (input.orderBy !== void 0) {
|
|
1776
|
+
parts.push(input.orderBy);
|
|
1777
|
+
}
|
|
1778
|
+
if (input.limitOffset !== void 0) {
|
|
1779
|
+
parts.push(input.limitOffset);
|
|
1780
|
+
}
|
|
1781
|
+
return drizzleOrm.sql.join(parts, drizzleOrm.sql` `);
|
|
1839
1782
|
}
|
|
1840
1783
|
|
|
1841
|
-
// src/query/compiler/
|
|
1842
|
-
function
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
case "
|
|
1847
|
-
|
|
1848
|
-
case "limit_offset":
|
|
1849
|
-
case "project":
|
|
1850
|
-
case "recursive_expand":
|
|
1851
|
-
case "sort":
|
|
1852
|
-
case "vector_knn": {
|
|
1853
|
-
collectPlanOperations(node.input, ops);
|
|
1854
|
-
return;
|
|
1784
|
+
// src/query/compiler/typed-json-extract.ts
|
|
1785
|
+
function compileTypedJsonExtract(input) {
|
|
1786
|
+
const { column, dialect, pointer, valueType } = input;
|
|
1787
|
+
const fallback = input.fallback ?? "json";
|
|
1788
|
+
switch (valueType) {
|
|
1789
|
+
case "string": {
|
|
1790
|
+
return dialect.jsonExtractText(column, pointer);
|
|
1855
1791
|
}
|
|
1856
|
-
case "
|
|
1857
|
-
|
|
1858
|
-
collectPlanOperations(node.right, ops);
|
|
1859
|
-
return;
|
|
1792
|
+
case "number": {
|
|
1793
|
+
return dialect.jsonExtractNumber(column, pointer);
|
|
1860
1794
|
}
|
|
1861
|
-
case "
|
|
1862
|
-
return;
|
|
1795
|
+
case "boolean": {
|
|
1796
|
+
return dialect.jsonExtractBoolean(column, pointer);
|
|
1863
1797
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
function findUnaryNodeInProjectChain(rootNode, op) {
|
|
1867
|
-
let currentNode = rootNode.input;
|
|
1868
|
-
for (; ; ) {
|
|
1869
|
-
if (currentNode.op === op) {
|
|
1870
|
-
return currentNode;
|
|
1798
|
+
case "date": {
|
|
1799
|
+
return dialect.jsonExtractDate(column, pointer);
|
|
1871
1800
|
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
continue;
|
|
1882
|
-
}
|
|
1883
|
-
case "project":
|
|
1884
|
-
case "scan":
|
|
1885
|
-
case "set_op": {
|
|
1886
|
-
return void 0;
|
|
1887
|
-
}
|
|
1801
|
+
case "array":
|
|
1802
|
+
case "object":
|
|
1803
|
+
case "embedding":
|
|
1804
|
+
case "unknown":
|
|
1805
|
+
case void 0: {
|
|
1806
|
+
return fallback === "text" ? dialect.jsonExtractText(column, pointer) : dialect.jsonExtract(column, pointer);
|
|
1807
|
+
}
|
|
1808
|
+
default: {
|
|
1809
|
+
return fallback === "text" ? dialect.jsonExtractText(column, pointer) : dialect.jsonExtract(column, pointer);
|
|
1888
1810
|
}
|
|
1889
1811
|
}
|
|
1890
1812
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
sortNode
|
|
1918
|
-
};
|
|
1813
|
+
var NODE_COLUMNS = [
|
|
1814
|
+
"id",
|
|
1815
|
+
"kind",
|
|
1816
|
+
"props",
|
|
1817
|
+
"version",
|
|
1818
|
+
"valid_from",
|
|
1819
|
+
"valid_to",
|
|
1820
|
+
"created_at",
|
|
1821
|
+
"updated_at",
|
|
1822
|
+
"deleted_at"
|
|
1823
|
+
];
|
|
1824
|
+
var EDGE_COLUMNS = [
|
|
1825
|
+
"id",
|
|
1826
|
+
"kind",
|
|
1827
|
+
"from_id",
|
|
1828
|
+
"to_id",
|
|
1829
|
+
"props",
|
|
1830
|
+
"valid_from",
|
|
1831
|
+
"valid_to",
|
|
1832
|
+
"created_at",
|
|
1833
|
+
"updated_at",
|
|
1834
|
+
"deleted_at"
|
|
1835
|
+
];
|
|
1836
|
+
var EMPTY_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
1837
|
+
function quoteIdentifier(identifier) {
|
|
1838
|
+
return drizzleOrm.sql.raw(`"${identifier.replaceAll('"', '""')}"`);
|
|
1919
1839
|
}
|
|
1920
|
-
function
|
|
1921
|
-
|
|
1922
|
-
if (
|
|
1923
|
-
|
|
1924
|
-
'Standard SQL emitter does not support plans containing "set_op" nodes',
|
|
1925
|
-
{ component: "plan-inspector" }
|
|
1926
|
-
);
|
|
1927
|
-
}
|
|
1928
|
-
if (shape.hasRecursiveExpand) {
|
|
1929
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1930
|
-
'Standard SQL emitter does not support plans containing "recursive_expand" nodes',
|
|
1931
|
-
{ component: "plan-inspector" }
|
|
1932
|
-
);
|
|
1933
|
-
}
|
|
1934
|
-
return shape;
|
|
1840
|
+
function shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns) {
|
|
1841
|
+
if (alwaysRequiredColumns?.has(column)) return true;
|
|
1842
|
+
if (requiredColumns === void 0) return true;
|
|
1843
|
+
return requiredColumns.has(column);
|
|
1935
1844
|
}
|
|
1936
|
-
function
|
|
1937
|
-
const
|
|
1938
|
-
if (
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
{ component: "plan-inspector" }
|
|
1942
|
-
);
|
|
1943
|
-
}
|
|
1944
|
-
if (shape.hasSetOperation) {
|
|
1945
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
1946
|
-
'Recursive SQL emitter does not support plans containing "set_op" nodes',
|
|
1947
|
-
{ component: "plan-inspector" }
|
|
1948
|
-
);
|
|
1845
|
+
function addRequiredColumn(requiredColumnsByAlias, alias, column) {
|
|
1846
|
+
const existing = requiredColumnsByAlias.get(alias);
|
|
1847
|
+
if (existing) {
|
|
1848
|
+
existing.add(column);
|
|
1849
|
+
return;
|
|
1949
1850
|
}
|
|
1950
|
-
|
|
1851
|
+
requiredColumnsByAlias.set(alias, /* @__PURE__ */ new Set([column]));
|
|
1951
1852
|
}
|
|
1952
|
-
function
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
return currentNode;
|
|
1957
|
-
}
|
|
1958
|
-
switch (currentNode.op) {
|
|
1959
|
-
case "aggregate":
|
|
1960
|
-
case "filter":
|
|
1961
|
-
case "join":
|
|
1962
|
-
case "project":
|
|
1963
|
-
case "recursive_expand":
|
|
1964
|
-
case "sort":
|
|
1965
|
-
case "vector_knn": {
|
|
1966
|
-
currentNode = currentNode.input;
|
|
1967
|
-
continue;
|
|
1968
|
-
}
|
|
1969
|
-
case "scan":
|
|
1970
|
-
case "set_op": {
|
|
1971
|
-
return void 0;
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1853
|
+
function markFieldRefAsRequired(requiredColumnsByAlias, field2) {
|
|
1854
|
+
const column = field2.path[0];
|
|
1855
|
+
if (column === void 0) return;
|
|
1856
|
+
addRequiredColumn(requiredColumnsByAlias, field2.alias, column);
|
|
1975
1857
|
}
|
|
1976
|
-
function
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
}
|
|
1982
|
-
switch (currentNode.op) {
|
|
1983
|
-
case "aggregate":
|
|
1984
|
-
case "filter":
|
|
1985
|
-
case "join":
|
|
1986
|
-
case "limit_offset":
|
|
1987
|
-
case "project":
|
|
1988
|
-
case "recursive_expand":
|
|
1989
|
-
case "vector_knn": {
|
|
1990
|
-
currentNode = currentNode.input;
|
|
1991
|
-
continue;
|
|
1992
|
-
}
|
|
1993
|
-
case "scan":
|
|
1994
|
-
case "set_op": {
|
|
1995
|
-
return void 0;
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1858
|
+
function mapSelectiveSystemFieldToColumn(field2) {
|
|
1859
|
+
if (field2 === "fromId") return "from_id";
|
|
1860
|
+
if (field2 === "toId") return "to_id";
|
|
1861
|
+
if (field2.startsWith("meta.")) {
|
|
1862
|
+
return field2.slice(5).replaceAll(/([A-Z])/g, "_$1").toLowerCase();
|
|
1998
1863
|
}
|
|
1864
|
+
return field2;
|
|
1999
1865
|
}
|
|
2000
|
-
function
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
{ component: "plan-inspector" }
|
|
1866
|
+
function markSelectiveFieldAsRequired(requiredColumnsByAlias, field2) {
|
|
1867
|
+
if (field2.isSystemField) {
|
|
1868
|
+
addRequiredColumn(
|
|
1869
|
+
requiredColumnsByAlias,
|
|
1870
|
+
field2.alias,
|
|
1871
|
+
mapSelectiveSystemFieldToColumn(field2.field)
|
|
2007
1872
|
);
|
|
1873
|
+
return;
|
|
2008
1874
|
}
|
|
2009
|
-
|
|
2010
|
-
const sortNode = findTopLevelSortNode(logicalPlan.root);
|
|
2011
|
-
return {
|
|
2012
|
-
hasLimitOffset: limitOffsetNode !== void 0,
|
|
2013
|
-
hasSetOperation: true,
|
|
2014
|
-
hasSort: sortNode !== void 0,
|
|
2015
|
-
limitOffsetNode,
|
|
2016
|
-
sortNode
|
|
2017
|
-
};
|
|
1875
|
+
addRequiredColumn(requiredColumnsByAlias, field2.alias, "props");
|
|
2018
1876
|
}
|
|
2019
|
-
function
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
{ component: "recursive-emitter" }
|
|
2031
|
-
);
|
|
2032
|
-
}
|
|
2033
|
-
if (planShape.hasLimitOffset && input.limitOffset === void 0) {
|
|
2034
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2035
|
-
"Recursive SQL emitter expected LIMIT/OFFSET clause for plan containing a limit_offset node",
|
|
2036
|
-
{ component: "recursive-emitter" }
|
|
2037
|
-
);
|
|
2038
|
-
}
|
|
2039
|
-
if (!planShape.hasLimitOffset && input.limitOffset !== void 0) {
|
|
2040
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2041
|
-
"Recursive SQL emitter received LIMIT/OFFSET clause for a plan without limit_offset nodes",
|
|
2042
|
-
{ component: "recursive-emitter" }
|
|
2043
|
-
);
|
|
1877
|
+
function isIdFieldRef(field2) {
|
|
1878
|
+
return field2.path.length === 1 && field2.path[0] === "id" && field2.jsonPointer === void 0;
|
|
1879
|
+
}
|
|
1880
|
+
function isAggregateExpr(source) {
|
|
1881
|
+
return "__type" in source && source.__type === "aggregate";
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
// src/query/compiler/emitter/standard-builders.ts
|
|
1885
|
+
function compileColumnReference(tableAlias, column) {
|
|
1886
|
+
if (tableAlias === void 0) {
|
|
1887
|
+
return drizzleOrm.sql.raw(column);
|
|
2044
1888
|
}
|
|
1889
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(tableAlias)}.${drizzleOrm.sql.raw(column)}`;
|
|
2045
1890
|
}
|
|
2046
|
-
function
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
1891
|
+
function compileNodeSelectColumns(tableAlias, alias, requiredColumns) {
|
|
1892
|
+
return NODE_COLUMNS.filter(
|
|
1893
|
+
(column) => column === "id" || column === "kind" || shouldProjectColumn(requiredColumns, column)
|
|
1894
|
+
).map(
|
|
1895
|
+
(column) => drizzleOrm.sql`${compileColumnReference(tableAlias, column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
function compileEdgeSelectColumns(tableAlias, alias, requiredColumns) {
|
|
1899
|
+
return EDGE_COLUMNS.filter(
|
|
1900
|
+
(column) => shouldProjectColumn(requiredColumns, column)
|
|
1901
|
+
).map(
|
|
1902
|
+
(column) => drizzleOrm.sql`${compileColumnReference(tableAlias, column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
function buildStandardStartCte(input) {
|
|
1906
|
+
const { ast, ctx, graphId, predicateIndex, requiredColumnsByAlias } = input;
|
|
1907
|
+
const alias = ast.start.alias;
|
|
1908
|
+
const kinds = ast.start.kinds;
|
|
1909
|
+
const kindFilter = compileKindFilter(drizzleOrm.sql.raw("kind"), kinds);
|
|
1910
|
+
const temporalFilter = input.temporalFilterPass.forAlias();
|
|
1911
|
+
const cteContext = { ...ctx, cteColumnPrefix: "" };
|
|
1912
|
+
const predicateClauses = compilePredicateClauses(
|
|
1913
|
+
getPredicatesForAlias(predicateIndex, alias, "node"),
|
|
1914
|
+
cteContext
|
|
1915
|
+
);
|
|
1916
|
+
const whereClauses = [
|
|
1917
|
+
drizzleOrm.sql`graph_id = ${graphId}`,
|
|
1918
|
+
kindFilter,
|
|
1919
|
+
temporalFilter,
|
|
1920
|
+
...predicateClauses
|
|
2054
1921
|
];
|
|
2055
|
-
|
|
2056
|
-
|
|
1922
|
+
const effectiveRequiredColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(alias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
1923
|
+
return drizzleOrm.sql`
|
|
1924
|
+
cte_${drizzleOrm.sql.raw(alias)} AS (
|
|
1925
|
+
SELECT ${drizzleOrm.sql.join(
|
|
1926
|
+
compileNodeSelectColumns(void 0, alias, effectiveRequiredColumns),
|
|
1927
|
+
drizzleOrm.sql`, `
|
|
1928
|
+
)}
|
|
1929
|
+
FROM ${ctx.schema.nodesTable}
|
|
1930
|
+
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
|
|
1931
|
+
)
|
|
1932
|
+
`;
|
|
1933
|
+
}
|
|
1934
|
+
function buildStandardTraversalCte(input) {
|
|
1935
|
+
const {
|
|
1936
|
+
ast,
|
|
1937
|
+
carryForwardPreviousColumns,
|
|
1938
|
+
ctx,
|
|
1939
|
+
graphId,
|
|
1940
|
+
materializeCte,
|
|
1941
|
+
predicateIndex,
|
|
1942
|
+
requiredColumnsByAlias,
|
|
1943
|
+
temporalFilterPass,
|
|
1944
|
+
traversalIndex,
|
|
1945
|
+
traversalLimit
|
|
1946
|
+
} = input;
|
|
1947
|
+
const traversal = ast.traversals[traversalIndex];
|
|
1948
|
+
const traversalLimitValue = traversalIndex === ast.traversals.length - 1 ? traversalLimit : void 0;
|
|
1949
|
+
const previousNodeKinds = getNodeKindsForAlias(ast, traversal.joinFromAlias);
|
|
1950
|
+
const directEdgeKinds = [...new Set(traversal.edgeKinds)];
|
|
1951
|
+
const inverseEdgeKinds = traversal.inverseEdgeKinds === void 0 ? [] : [...new Set(traversal.inverseEdgeKinds)];
|
|
1952
|
+
const nodeKinds = traversal.nodeKinds;
|
|
1953
|
+
const nodeKindFilter = compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds);
|
|
1954
|
+
const edgeTemporalFilter = temporalFilterPass.forAlias("e");
|
|
1955
|
+
const nodeTemporalFilter = temporalFilterPass.forAlias("n");
|
|
1956
|
+
const nodeCteContext = {
|
|
1957
|
+
...ctx,
|
|
1958
|
+
cteColumnPrefix: "n"
|
|
1959
|
+
};
|
|
1960
|
+
const nodePredicateClauses = compilePredicateClauses(
|
|
1961
|
+
getPredicatesForAlias(predicateIndex, traversal.nodeAlias, "node"),
|
|
1962
|
+
nodeCteContext
|
|
1963
|
+
);
|
|
1964
|
+
const edgeCteContext = {
|
|
1965
|
+
...ctx,
|
|
1966
|
+
cteColumnPrefix: "e"
|
|
1967
|
+
};
|
|
1968
|
+
const edgePredicateClauses = compilePredicateClauses(
|
|
1969
|
+
getPredicatesForAlias(predicateIndex, traversal.edgeAlias, "edge"),
|
|
1970
|
+
edgeCteContext
|
|
1971
|
+
);
|
|
1972
|
+
const baseWhereClauses = [
|
|
1973
|
+
drizzleOrm.sql`e.graph_id = ${graphId}`,
|
|
1974
|
+
nodeKindFilter,
|
|
1975
|
+
edgeTemporalFilter,
|
|
1976
|
+
nodeTemporalFilter,
|
|
1977
|
+
...nodePredicateClauses,
|
|
1978
|
+
...edgePredicateClauses
|
|
1979
|
+
];
|
|
1980
|
+
const previousAlias = traversal.joinFromAlias;
|
|
1981
|
+
const edgeAlias = traversal.edgeAlias;
|
|
1982
|
+
const nodeAlias = traversal.nodeAlias;
|
|
1983
|
+
const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
1984
|
+
const requiredEdgeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(edgeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
1985
|
+
const previousRowColumns = carryForwardPreviousColumns ? [drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.*`] : [
|
|
1986
|
+
drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id AS ${drizzleOrm.sql.raw(previousAlias)}_id`,
|
|
1987
|
+
drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind AS ${drizzleOrm.sql.raw(previousAlias)}_kind`
|
|
1988
|
+
];
|
|
1989
|
+
const selectColumns = [
|
|
1990
|
+
...previousRowColumns,
|
|
1991
|
+
...compileEdgeSelectColumns("e", edgeAlias, requiredEdgeColumns),
|
|
1992
|
+
...compileNodeSelectColumns("n", nodeAlias, requiredNodeColumns)
|
|
1993
|
+
];
|
|
1994
|
+
const cteMaterialization = materializeCte ? drizzleOrm.sql`MATERIALIZED ` : drizzleOrm.sql``;
|
|
1995
|
+
function compileTraversalBranch(branch) {
|
|
1996
|
+
const whereClauses = [
|
|
1997
|
+
...baseWhereClauses,
|
|
1998
|
+
compileKindFilter(drizzleOrm.sql.raw("e.kind"), branch.edgeKinds),
|
|
1999
|
+
compileKindFilter(
|
|
2000
|
+
drizzleOrm.sql.raw(`e.${branch.joinKindField}`),
|
|
2001
|
+
previousNodeKinds
|
|
2002
|
+
),
|
|
2003
|
+
compileKindFilter(drizzleOrm.sql.raw(`e.${branch.targetKindField}`), nodeKinds)
|
|
2004
|
+
];
|
|
2005
|
+
if (branch.duplicateGuard !== void 0) {
|
|
2006
|
+
whereClauses.push(branch.duplicateGuard);
|
|
2007
|
+
}
|
|
2008
|
+
return drizzleOrm.sql`
|
|
2009
|
+
SELECT ${drizzleOrm.sql.join(selectColumns, drizzleOrm.sql`, `)}
|
|
2010
|
+
FROM cte_${drizzleOrm.sql.raw(previousAlias)}
|
|
2011
|
+
JOIN ${ctx.schema.edgesTable} e ON cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id = e.${drizzleOrm.sql.raw(branch.joinField)}
|
|
2012
|
+
AND cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind = e.${drizzleOrm.sql.raw(branch.joinKindField)}
|
|
2013
|
+
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
2014
|
+
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
2015
|
+
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
2016
|
+
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
|
|
2017
|
+
`;
|
|
2057
2018
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2019
|
+
const directJoinField = traversal.direction === "out" ? "from_id" : "to_id";
|
|
2020
|
+
const directTargetField = traversal.direction === "out" ? "to_id" : "from_id";
|
|
2021
|
+
const directJoinKindField = traversal.direction === "out" ? "from_kind" : "to_kind";
|
|
2022
|
+
const directTargetKindField = traversal.direction === "out" ? "to_kind" : "from_kind";
|
|
2023
|
+
const directBranch = compileTraversalBranch({
|
|
2024
|
+
edgeKinds: directEdgeKinds,
|
|
2025
|
+
joinField: directJoinField,
|
|
2026
|
+
joinKindField: directJoinKindField,
|
|
2027
|
+
targetField: directTargetField,
|
|
2028
|
+
targetKindField: directTargetKindField
|
|
2029
|
+
});
|
|
2030
|
+
if (inverseEdgeKinds.length === 0) {
|
|
2031
|
+
if (traversalLimitValue !== void 0) {
|
|
2032
|
+
return drizzleOrm.sql`
|
|
2033
|
+
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2034
|
+
SELECT * FROM (
|
|
2035
|
+
${directBranch}
|
|
2036
|
+
) AS traversal_rows
|
|
2037
|
+
LIMIT ${traversalLimitValue}
|
|
2038
|
+
)
|
|
2039
|
+
`;
|
|
2040
|
+
}
|
|
2041
|
+
return drizzleOrm.sql`
|
|
2042
|
+
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2043
|
+
${directBranch}
|
|
2044
|
+
)
|
|
2045
|
+
`;
|
|
2046
|
+
}
|
|
2047
|
+
const inverseJoinField = traversal.direction === "out" ? "to_id" : "from_id";
|
|
2048
|
+
const inverseTargetField = traversal.direction === "out" ? "from_id" : "to_id";
|
|
2049
|
+
const inverseJoinKindField = traversal.direction === "out" ? "to_kind" : "from_kind";
|
|
2050
|
+
const inverseTargetKindField = traversal.direction === "out" ? "from_kind" : "to_kind";
|
|
2051
|
+
const overlappingKinds = inverseEdgeKinds.filter(
|
|
2052
|
+
(kind) => directEdgeKinds.includes(kind)
|
|
2053
|
+
);
|
|
2054
|
+
const duplicateGuard = overlappingKinds.length > 0 ? drizzleOrm.sql`NOT (e.from_id = e.to_id AND ${compileKindFilter(
|
|
2055
|
+
drizzleOrm.sql.raw("e.kind"),
|
|
2056
|
+
overlappingKinds
|
|
2057
|
+
)})` : void 0;
|
|
2058
|
+
const inverseBranch = compileTraversalBranch({
|
|
2059
|
+
duplicateGuard,
|
|
2060
|
+
edgeKinds: inverseEdgeKinds,
|
|
2061
|
+
joinField: inverseJoinField,
|
|
2062
|
+
joinKindField: inverseJoinKindField,
|
|
2063
|
+
targetField: inverseTargetField,
|
|
2064
|
+
targetKindField: inverseTargetKindField
|
|
2065
|
+
});
|
|
2066
|
+
if (traversalLimitValue !== void 0) {
|
|
2067
|
+
return drizzleOrm.sql`
|
|
2068
|
+
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2069
|
+
SELECT * FROM (
|
|
2070
|
+
${directBranch}
|
|
2071
|
+
UNION ALL
|
|
2072
|
+
${inverseBranch}
|
|
2073
|
+
) AS traversal_rows
|
|
2074
|
+
LIMIT ${traversalLimitValue}
|
|
2075
|
+
)
|
|
2076
|
+
`;
|
|
2077
|
+
}
|
|
2078
|
+
return drizzleOrm.sql`
|
|
2079
|
+
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2080
|
+
${directBranch}
|
|
2081
|
+
UNION ALL
|
|
2082
|
+
${inverseBranch}
|
|
2083
|
+
)
|
|
2084
|
+
`;
|
|
2085
|
+
}
|
|
2086
|
+
function compileAggregateExprFromSource(expr, dialect) {
|
|
2087
|
+
const { field: field2 } = expr;
|
|
2088
|
+
const fn = expr.function;
|
|
2089
|
+
switch (fn) {
|
|
2090
|
+
case "count":
|
|
2091
|
+
case "countDistinct":
|
|
2092
|
+
case "sum":
|
|
2093
|
+
case "avg":
|
|
2094
|
+
case "min":
|
|
2095
|
+
case "max": {
|
|
2096
|
+
const cteAlias = `cte_${field2.alias}`;
|
|
2097
|
+
const column = compileFieldValue(
|
|
2098
|
+
field2,
|
|
2099
|
+
dialect,
|
|
2100
|
+
field2.valueType,
|
|
2101
|
+
cteAlias
|
|
2102
|
+
);
|
|
2103
|
+
if (fn === "countDistinct") {
|
|
2104
|
+
return drizzleOrm.sql`COUNT(DISTINCT ${column})`;
|
|
2105
|
+
}
|
|
2106
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(fn.toUpperCase())}(${column})`;
|
|
2107
|
+
}
|
|
2108
|
+
default: {
|
|
2109
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2110
|
+
`Unknown aggregate function: ${String(fn)}`
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
function compileProjectedSource(field2, dialect) {
|
|
2116
|
+
if (isAggregateExpr(field2.source)) {
|
|
2117
|
+
return compileAggregateExprFromSource(field2.source, dialect);
|
|
2118
|
+
}
|
|
2119
|
+
const cteAlias = field2.cteAlias ?? `cte_${field2.source.alias}`;
|
|
2120
|
+
return compileFieldValue(
|
|
2121
|
+
field2.source,
|
|
2122
|
+
dialect,
|
|
2123
|
+
field2.source.valueType,
|
|
2124
|
+
cteAlias
|
|
2125
|
+
);
|
|
2126
|
+
}
|
|
2127
|
+
function buildStandardProjection(input) {
|
|
2128
|
+
const { ast, collapsedTraversalCteAlias, dialect } = input;
|
|
2129
|
+
if (ast.selectiveFields && ast.selectiveFields.length > 0) {
|
|
2130
|
+
return compileSelectiveProjection(
|
|
2131
|
+
ast.selectiveFields,
|
|
2132
|
+
dialect,
|
|
2133
|
+
ast,
|
|
2134
|
+
collapsedTraversalCteAlias
|
|
2135
|
+
);
|
|
2136
|
+
}
|
|
2137
|
+
const fields = ast.projection.fields;
|
|
2138
|
+
if (fields.length === 0) {
|
|
2139
|
+
return drizzleOrm.sql.raw("*");
|
|
2140
|
+
}
|
|
2141
|
+
const projectedFields = fields.map((field2) => {
|
|
2142
|
+
const source = compileProjectedSource(field2, dialect);
|
|
2143
|
+
return drizzleOrm.sql`${source} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2144
|
+
});
|
|
2145
|
+
return drizzleOrm.sql.join(projectedFields, drizzleOrm.sql`, `);
|
|
2146
|
+
}
|
|
2147
|
+
function compileSelectiveProjection(fields, dialect, ast, collapsedTraversalCteAlias) {
|
|
2148
|
+
const aliasToCte = /* @__PURE__ */ new Map([
|
|
2149
|
+
[ast.start.alias, `cte_${ast.start.alias}`]
|
|
2150
|
+
]);
|
|
2151
|
+
for (const traversal of ast.traversals) {
|
|
2152
|
+
aliasToCte.set(traversal.nodeAlias, `cte_${traversal.nodeAlias}`);
|
|
2153
|
+
aliasToCte.set(traversal.edgeAlias, `cte_${traversal.nodeAlias}`);
|
|
2154
|
+
}
|
|
2155
|
+
const columns = fields.map((field2) => {
|
|
2156
|
+
const cteAlias = collapsedTraversalCteAlias ?? aliasToCte.get(field2.alias) ?? `cte_${field2.alias}`;
|
|
2157
|
+
if (field2.isSystemField) {
|
|
2158
|
+
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
2159
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2160
|
+
}
|
|
2161
|
+
const propsColumn = `${field2.alias}_props`;
|
|
2162
|
+
const column = drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(propsColumn)}`;
|
|
2163
|
+
const pointer = chunkP5CNM325_cjs.jsonPointer([field2.field]);
|
|
2164
|
+
const extracted = compileTypedJsonExtract({
|
|
2165
|
+
column,
|
|
2166
|
+
dialect,
|
|
2167
|
+
pointer,
|
|
2168
|
+
valueType: field2.valueType
|
|
2169
|
+
});
|
|
2170
|
+
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2171
|
+
});
|
|
2172
|
+
return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
|
|
2173
|
+
}
|
|
2174
|
+
function buildStandardFromClause(input) {
|
|
2175
|
+
const { ast, collapsedTraversalCteAlias, vectorPredicate } = input;
|
|
2176
|
+
if (collapsedTraversalCteAlias !== void 0) {
|
|
2177
|
+
return drizzleOrm.sql`FROM ${drizzleOrm.sql.raw(collapsedTraversalCteAlias)}`;
|
|
2178
|
+
}
|
|
2179
|
+
const startAlias = ast.start.alias;
|
|
2180
|
+
const fromClause = drizzleOrm.sql`FROM cte_${drizzleOrm.sql.raw(startAlias)}`;
|
|
2181
|
+
const joins = [];
|
|
2182
|
+
for (const traversal of ast.traversals) {
|
|
2183
|
+
const cteAlias = `cte_${traversal.nodeAlias}`;
|
|
2184
|
+
const previousAlias = traversal.joinFromAlias;
|
|
2185
|
+
const joinType = traversal.optional ? "LEFT JOIN" : "INNER JOIN";
|
|
2186
|
+
joins.push(
|
|
2187
|
+
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`
|
|
2188
|
+
);
|
|
2189
|
+
}
|
|
2190
|
+
if (vectorPredicate) {
|
|
2191
|
+
const nodeAlias = vectorPredicate.field.alias;
|
|
2192
|
+
joins.push(
|
|
2193
|
+
drizzleOrm.sql`INNER JOIN cte_embeddings ON cte_embeddings.node_id = cte_${drizzleOrm.sql.raw(nodeAlias)}.${drizzleOrm.sql.raw(nodeAlias)}_id`
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
return joins.length === 0 ? fromClause : drizzleOrm.sql`${fromClause} ${drizzleOrm.sql.join(joins, drizzleOrm.sql` `)}`;
|
|
2197
|
+
}
|
|
2198
|
+
function buildStandardOrderBy(input) {
|
|
2199
|
+
const { ast, collapsedTraversalCteAlias, dialect } = input;
|
|
2200
|
+
if (!ast.orderBy || ast.orderBy.length === 0) {
|
|
2201
|
+
return void 0;
|
|
2202
|
+
}
|
|
2203
|
+
const parts = [];
|
|
2204
|
+
for (const orderSpec of ast.orderBy) {
|
|
2205
|
+
const valueType = orderSpec.field.valueType;
|
|
2206
|
+
if (valueType === "array" || valueType === "object") {
|
|
2207
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2208
|
+
"Ordering by JSON arrays or objects is not supported"
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
2211
|
+
const cteAlias = collapsedTraversalCteAlias ?? `cte_${orderSpec.field.alias}`;
|
|
2212
|
+
const field2 = compileFieldValue(
|
|
2213
|
+
orderSpec.field,
|
|
2214
|
+
dialect,
|
|
2215
|
+
valueType,
|
|
2216
|
+
cteAlias
|
|
2217
|
+
);
|
|
2218
|
+
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
2219
|
+
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
2220
|
+
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
2221
|
+
parts.push(
|
|
2222
|
+
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
2223
|
+
drizzleOrm.sql`${field2} ${direction}`
|
|
2224
|
+
);
|
|
2225
|
+
}
|
|
2226
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
2227
|
+
}
|
|
2228
|
+
function fieldRefKey(field2) {
|
|
2229
|
+
const pointer = field2.jsonPointer ?? "";
|
|
2230
|
+
return `${field2.alias}:${field2.path.join(".")}:${pointer}`;
|
|
2231
|
+
}
|
|
2232
|
+
function buildStandardGroupBy(input) {
|
|
2233
|
+
const { ast, dialect } = input;
|
|
2234
|
+
if (!ast.groupBy || ast.groupBy.fields.length === 0) {
|
|
2235
|
+
return void 0;
|
|
2236
|
+
}
|
|
2237
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
2238
|
+
const allFields = [];
|
|
2239
|
+
for (const projectedField of ast.projection.fields) {
|
|
2240
|
+
if (projectedField.source.__type === "field_ref") {
|
|
2241
|
+
const key = fieldRefKey(projectedField.source);
|
|
2242
|
+
if (!seenKeys.has(key)) {
|
|
2243
|
+
seenKeys.add(key);
|
|
2244
|
+
allFields.push(projectedField.source);
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
for (const field2 of ast.groupBy.fields) {
|
|
2249
|
+
const key = fieldRefKey(field2);
|
|
2250
|
+
if (!seenKeys.has(key)) {
|
|
2251
|
+
seenKeys.add(key);
|
|
2252
|
+
allFields.push(field2);
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
if (allFields.length === 0) {
|
|
2256
|
+
return void 0;
|
|
2257
|
+
}
|
|
2258
|
+
const parts = allFields.map(
|
|
2259
|
+
(field2) => compileFieldValue(field2, dialect, field2.valueType, `cte_${field2.alias}`)
|
|
2260
|
+
);
|
|
2261
|
+
return drizzleOrm.sql`GROUP BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
2262
|
+
}
|
|
2263
|
+
function buildStandardHaving(input) {
|
|
2264
|
+
const { ast, ctx } = input;
|
|
2265
|
+
if (!ast.having) {
|
|
2266
|
+
return void 0;
|
|
2267
|
+
}
|
|
2268
|
+
const condition = compilePredicateExpression(ast.having, ctx);
|
|
2269
|
+
return drizzleOrm.sql`HAVING ${condition}`;
|
|
2270
|
+
}
|
|
2271
|
+
function buildStandardEmbeddingsCte(input) {
|
|
2272
|
+
const { ctx, graphId, vectorPredicate } = input;
|
|
2273
|
+
const { dialect } = ctx;
|
|
2274
|
+
const { field: field2, metric, minScore, queryEmbedding } = vectorPredicate;
|
|
2275
|
+
const fieldPath = field2.jsonPointer ? field2.jsonPointer : field2.path.length > 1 && field2.path[0] === "props" ? `/${field2.path.slice(1).join("/")}` : `/${field2.path.join("/")}`;
|
|
2276
|
+
const distanceExpr = dialect.vectorDistance(
|
|
2277
|
+
drizzleOrm.sql.raw("embedding"),
|
|
2278
|
+
queryEmbedding,
|
|
2279
|
+
metric
|
|
2280
|
+
);
|
|
2281
|
+
const conditions = [
|
|
2282
|
+
drizzleOrm.sql`graph_id = ${graphId}`,
|
|
2283
|
+
drizzleOrm.sql`field_path = ${fieldPath}`
|
|
2284
|
+
];
|
|
2285
|
+
if (minScore !== void 0) {
|
|
2286
|
+
conditions.push(
|
|
2287
|
+
compileVectorMinScoreCondition(distanceExpr, metric, minScore)
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
const scoreExpr = compileVectorScoreExpression(distanceExpr, metric);
|
|
2291
|
+
return drizzleOrm.sql`
|
|
2292
|
+
cte_embeddings AS (
|
|
2293
|
+
SELECT
|
|
2294
|
+
node_id,
|
|
2295
|
+
${distanceExpr} AS distance,
|
|
2296
|
+
${scoreExpr} AS score
|
|
2297
|
+
FROM ${ctx.schema.embeddingsTable}
|
|
2298
|
+
WHERE ${drizzleOrm.sql.join(conditions, drizzleOrm.sql` AND `)}
|
|
2299
|
+
ORDER BY ${distanceExpr} ASC
|
|
2300
|
+
)
|
|
2301
|
+
`;
|
|
2302
|
+
}
|
|
2303
|
+
function compileVectorScoreExpression(distanceExpr, metric) {
|
|
2304
|
+
switch (metric) {
|
|
2305
|
+
case "cosine": {
|
|
2306
|
+
return drizzleOrm.sql`(1.0 - ${distanceExpr})`;
|
|
2307
|
+
}
|
|
2308
|
+
case "l2":
|
|
2309
|
+
case "inner_product": {
|
|
2310
|
+
return distanceExpr;
|
|
2311
|
+
}
|
|
2060
2312
|
}
|
|
2061
|
-
return drizzleOrm.sql.join(parts, drizzleOrm.sql` `);
|
|
2062
2313
|
}
|
|
2063
|
-
function
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2314
|
+
function compileVectorMinScoreCondition(distanceExpr, metric, minScore) {
|
|
2315
|
+
switch (metric) {
|
|
2316
|
+
case "cosine": {
|
|
2317
|
+
const threshold = 1 - minScore;
|
|
2318
|
+
return drizzleOrm.sql`${distanceExpr} <= ${threshold}`;
|
|
2319
|
+
}
|
|
2320
|
+
case "l2": {
|
|
2321
|
+
return drizzleOrm.sql`${distanceExpr} <= ${minScore}`;
|
|
2322
|
+
}
|
|
2323
|
+
case "inner_product": {
|
|
2324
|
+
const negativeThreshold = -minScore;
|
|
2325
|
+
return drizzleOrm.sql`${distanceExpr} <= ${negativeThreshold}`;
|
|
2326
|
+
}
|
|
2071
2327
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2328
|
+
}
|
|
2329
|
+
function buildStandardVectorOrderBy(input) {
|
|
2330
|
+
const { ast, dialect } = input;
|
|
2331
|
+
const distanceOrder = drizzleOrm.sql`cte_embeddings.distance ASC`;
|
|
2332
|
+
const additionalOrders = [];
|
|
2333
|
+
if (ast.orderBy && ast.orderBy.length > 0) {
|
|
2334
|
+
for (const orderSpec of ast.orderBy) {
|
|
2335
|
+
const valueType = orderSpec.field.valueType;
|
|
2336
|
+
if (valueType === "array" || valueType === "object") {
|
|
2337
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2338
|
+
"Ordering by JSON arrays or objects is not supported"
|
|
2339
|
+
);
|
|
2340
|
+
}
|
|
2341
|
+
const cteAlias = `cte_${orderSpec.field.alias}`;
|
|
2342
|
+
const field2 = compileFieldValue(
|
|
2343
|
+
orderSpec.field,
|
|
2344
|
+
dialect,
|
|
2345
|
+
valueType,
|
|
2346
|
+
cteAlias
|
|
2347
|
+
);
|
|
2348
|
+
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
2349
|
+
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
2350
|
+
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
2351
|
+
additionalOrders.push(
|
|
2352
|
+
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
2353
|
+
drizzleOrm.sql`${field2} ${direction}`
|
|
2077
2354
|
);
|
|
2078
2355
|
}
|
|
2079
|
-
return;
|
|
2080
|
-
}
|
|
2081
|
-
const limitOffsetClauseCount = shape.limitOffsetNode === void 0 ? 0 : (shape.limitOffsetNode.limit === void 0 ? 0 : 1) + (shape.limitOffsetNode.offset === void 0 ? 0 : 1);
|
|
2082
|
-
const expectedClauseCount = (shape.sortNode === void 0 ? 0 : 1) + limitOffsetClauseCount;
|
|
2083
|
-
if (suffixClauses.length !== expectedClauseCount) {
|
|
2084
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2085
|
-
`Set-operation SQL emitter expected ${String(expectedClauseCount)} top-level suffix clause(s) from logical plan, got ${String(suffixClauses.length)}`,
|
|
2086
|
-
{ component: "set-operation-emitter" }
|
|
2087
|
-
);
|
|
2088
2356
|
}
|
|
2357
|
+
const allOrders = [distanceOrder, ...additionalOrders];
|
|
2358
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(allOrders, drizzleOrm.sql`, `)}`;
|
|
2089
2359
|
}
|
|
2090
|
-
function
|
|
2091
|
-
|
|
2092
|
-
input.logicalPlan,
|
|
2093
|
-
input.suffixClauses
|
|
2094
|
-
);
|
|
2360
|
+
function buildLimitOffsetClause(input) {
|
|
2361
|
+
const { limit, offset } = input;
|
|
2095
2362
|
const parts = [];
|
|
2096
|
-
if (
|
|
2097
|
-
parts.push(drizzleOrm.sql`
|
|
2363
|
+
if (limit !== void 0) {
|
|
2364
|
+
parts.push(drizzleOrm.sql`LIMIT ${limit}`);
|
|
2098
2365
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
parts.push(...input.suffixClauses);
|
|
2366
|
+
if (offset !== void 0) {
|
|
2367
|
+
parts.push(drizzleOrm.sql`OFFSET ${offset}`);
|
|
2102
2368
|
}
|
|
2103
|
-
return drizzleOrm.sql.join(parts, drizzleOrm.sql` `);
|
|
2369
|
+
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
2104
2370
|
}
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2371
|
+
|
|
2372
|
+
// src/query/compiler/passes/recursive.ts
|
|
2373
|
+
function runRecursiveTraversalSelectionPass(ast) {
|
|
2374
|
+
const variableLengthTraversal = ast.traversals.find(
|
|
2375
|
+
(traversal) => traversal.variableLength !== void 0
|
|
2376
|
+
);
|
|
2377
|
+
if (variableLengthTraversal === void 0) {
|
|
2378
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError("No variable-length traversal found");
|
|
2112
2379
|
}
|
|
2113
|
-
if (
|
|
2114
|
-
throw new chunk44SXEVF4_cjs.
|
|
2115
|
-
"
|
|
2116
|
-
{ component: "standard-emitter" }
|
|
2380
|
+
if (ast.traversals.length > 1) {
|
|
2381
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2382
|
+
"Variable-length traversals with multiple traversals are not yet supported. Please use a single variable-length traversal."
|
|
2117
2383
|
);
|
|
2118
2384
|
}
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2385
|
+
return variableLengthTraversal;
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
// src/query/compiler/passes/runner.ts
|
|
2389
|
+
function runCompilerPass(state, pass) {
|
|
2390
|
+
const output = pass.execute(state);
|
|
2391
|
+
return {
|
|
2392
|
+
state: pass.update(state, output)
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
function compileTemporalFilter(options) {
|
|
2396
|
+
const { mode, asOf, tableAlias, currentTimestamp } = options;
|
|
2397
|
+
const prefix = tableAlias ? drizzleOrm.sql.raw(`${tableAlias}.`) : drizzleOrm.sql.raw("");
|
|
2398
|
+
const deletedAt = drizzleOrm.sql`${prefix}deleted_at`;
|
|
2399
|
+
const validFrom = drizzleOrm.sql`${prefix}valid_from`;
|
|
2400
|
+
const validTo = drizzleOrm.sql`${prefix}valid_to`;
|
|
2401
|
+
switch (mode) {
|
|
2402
|
+
case "current": {
|
|
2403
|
+
const now = currentTimestamp ?? drizzleOrm.sql`CURRENT_TIMESTAMP`;
|
|
2404
|
+
return drizzleOrm.sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${now}) AND (${validTo} IS NULL OR ${validTo} > ${now})`;
|
|
2405
|
+
}
|
|
2406
|
+
case "asOf": {
|
|
2407
|
+
const timestamp = asOf;
|
|
2408
|
+
return drizzleOrm.sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${timestamp}) AND (${validTo} IS NULL OR ${validTo} > ${timestamp})`;
|
|
2409
|
+
}
|
|
2410
|
+
case "includeEnded": {
|
|
2411
|
+
return drizzleOrm.sql`${deletedAt} IS NULL`;
|
|
2412
|
+
}
|
|
2413
|
+
case "includeTombstones": {
|
|
2414
|
+
return drizzleOrm.sql.raw("1=1");
|
|
2415
|
+
}
|
|
2125
2416
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2417
|
+
}
|
|
2418
|
+
function extractTemporalOptions(ast, tableAlias) {
|
|
2419
|
+
return {
|
|
2420
|
+
mode: ast.temporalMode.mode,
|
|
2421
|
+
asOf: ast.temporalMode.asOf,
|
|
2422
|
+
tableAlias
|
|
2423
|
+
};
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
// src/query/compiler/passes/temporal.ts
|
|
2427
|
+
function createTemporalFilterPass(ast, currentTimestamp) {
|
|
2428
|
+
return {
|
|
2429
|
+
forAlias(tableAlias) {
|
|
2430
|
+
return compileTemporalFilter({
|
|
2431
|
+
...extractTemporalOptions(ast, tableAlias),
|
|
2432
|
+
currentTimestamp
|
|
2433
|
+
});
|
|
2434
|
+
}
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
// src/query/compiler/passes/vector.ts
|
|
2439
|
+
function runVectorPredicatePass(ast, dialect) {
|
|
2440
|
+
const vectorPredicates = extractVectorSimilarityPredicates(ast.predicates);
|
|
2441
|
+
if (vectorPredicates.length > 1) {
|
|
2442
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2443
|
+
"Multiple vector similarity predicates in a single query are not supported"
|
|
2130
2444
|
);
|
|
2131
2445
|
}
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
{ component: "standard-emitter" }
|
|
2136
|
-
);
|
|
2446
|
+
const vectorPredicate = vectorPredicates[0];
|
|
2447
|
+
if (vectorPredicate === void 0) {
|
|
2448
|
+
return { vectorPredicate: void 0 };
|
|
2137
2449
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2450
|
+
const vectorStrategy = dialect.capabilities.vectorPredicateStrategy;
|
|
2451
|
+
if (vectorStrategy === "unsupported" || !dialect.supportsVectors) {
|
|
2452
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2453
|
+
`Vector similarity predicates are not supported for dialect "${dialect.name}"`
|
|
2142
2454
|
);
|
|
2143
2455
|
}
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
if (input.ctes.length > 0) {
|
|
2149
|
-
parts.push(drizzleOrm.sql`WITH ${drizzleOrm.sql.join([...input.ctes], drizzleOrm.sql`, `)}`);
|
|
2456
|
+
if (!dialect.capabilities.vectorMetrics.includes(vectorPredicate.metric)) {
|
|
2457
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2458
|
+
`Vector metric "${vectorPredicate.metric}" is not supported for dialect "${dialect.name}"`
|
|
2459
|
+
);
|
|
2150
2460
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2461
|
+
if (!Number.isFinite(vectorPredicate.limit) || vectorPredicate.limit <= 0) {
|
|
2462
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2463
|
+
`Vector predicate limit must be a positive finite number, got ${String(vectorPredicate.limit)}`
|
|
2464
|
+
);
|
|
2154
2465
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2466
|
+
const { minScore } = vectorPredicate;
|
|
2467
|
+
if (minScore !== void 0) {
|
|
2468
|
+
if (!Number.isFinite(minScore)) {
|
|
2469
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2470
|
+
`Vector minScore must be a finite number, got ${String(minScore)}`
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
if (vectorPredicate.metric === "cosine" && (minScore < -1 || minScore > 1)) {
|
|
2474
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2475
|
+
`Cosine minScore must be between -1 and 1, got ${String(minScore)}`
|
|
2476
|
+
);
|
|
2477
|
+
}
|
|
2157
2478
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2479
|
+
return { vectorPredicate };
|
|
2480
|
+
}
|
|
2481
|
+
function resolveVectorAwareLimit(astLimit, vectorPredicate) {
|
|
2482
|
+
if (vectorPredicate === void 0) {
|
|
2483
|
+
return astLimit;
|
|
2160
2484
|
}
|
|
2161
|
-
if (
|
|
2162
|
-
|
|
2485
|
+
if (astLimit === void 0) {
|
|
2486
|
+
return vectorPredicate.limit;
|
|
2163
2487
|
}
|
|
2164
|
-
return
|
|
2165
|
-
}
|
|
2166
|
-
var EMPTY_PREDICATES = [];
|
|
2167
|
-
function buildPredicateIndexKey(alias, targetType) {
|
|
2168
|
-
return `${alias}\0${targetType}`;
|
|
2169
|
-
}
|
|
2170
|
-
function resolvePredicateTargetType(predicate2) {
|
|
2171
|
-
return predicate2.targetType === "edge" ? "edge" : "node";
|
|
2488
|
+
return Math.min(astLimit, vectorPredicate.limit);
|
|
2172
2489
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
)
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2490
|
+
|
|
2491
|
+
// src/query/compiler/plan/lowering.ts
|
|
2492
|
+
function createPlanNodeIdFactory() {
|
|
2493
|
+
let current = 0;
|
|
2494
|
+
return function nextPlanNodeId() {
|
|
2495
|
+
current += 1;
|
|
2496
|
+
return `plan_${current.toString(36)}`;
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
function extractAggregateExpressions(ast) {
|
|
2500
|
+
const aggregates = [];
|
|
2501
|
+
for (const field2 of ast.projection.fields) {
|
|
2502
|
+
if ("__type" in field2.source && field2.source.__type === "aggregate") {
|
|
2503
|
+
aggregates.push(field2.source);
|
|
2185
2504
|
}
|
|
2186
2505
|
}
|
|
2187
|
-
return
|
|
2188
|
-
}
|
|
2189
|
-
function getPredicatesForAlias(predicateIndex, alias, targetType) {
|
|
2190
|
-
return predicateIndex.byAliasAndType.get(
|
|
2191
|
-
buildPredicateIndexKey(alias, targetType)
|
|
2192
|
-
) ?? EMPTY_PREDICATES;
|
|
2506
|
+
return aggregates;
|
|
2193
2507
|
}
|
|
2194
|
-
function
|
|
2195
|
-
return predicates.
|
|
2196
|
-
|
|
2197
|
-
|
|
2508
|
+
function getAliasPredicates(ast, alias, predicateTargetType) {
|
|
2509
|
+
return ast.predicates.filter((predicate2) => {
|
|
2510
|
+
const targetType = predicate2.targetType ?? "node";
|
|
2511
|
+
return predicate2.targetAlias === alias && targetType === predicateTargetType;
|
|
2512
|
+
});
|
|
2198
2513
|
}
|
|
2199
|
-
function
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
if (kinds.length === 1) {
|
|
2204
|
-
return drizzleOrm.sql`${column} = ${kinds[0]}`;
|
|
2514
|
+
function wrapWithAliasFilterNode(currentNode, ast, alias, predicateTargetType, nextPlanNodeId) {
|
|
2515
|
+
const aliasPredicates = getAliasPredicates(ast, alias, predicateTargetType);
|
|
2516
|
+
if (aliasPredicates.length === 0) {
|
|
2517
|
+
return currentNode;
|
|
2205
2518
|
}
|
|
2206
|
-
return
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2519
|
+
return {
|
|
2520
|
+
alias,
|
|
2521
|
+
id: nextPlanNodeId(),
|
|
2522
|
+
input: currentNode,
|
|
2523
|
+
op: "filter",
|
|
2524
|
+
predicateTargetType,
|
|
2525
|
+
predicates: aliasPredicates.map((predicate2) => predicate2.expression)
|
|
2526
|
+
};
|
|
2210
2527
|
}
|
|
2211
|
-
function
|
|
2212
|
-
|
|
2213
|
-
|
|
2528
|
+
function appendAggregateSortLimitAndProjectNodes(currentNode, ast, nextPlanNodeId, limit, collapsedTraversalCteAlias) {
|
|
2529
|
+
let node = currentNode;
|
|
2530
|
+
const aggregateExpressions = extractAggregateExpressions(ast);
|
|
2531
|
+
if (aggregateExpressions.length > 0 || ast.groupBy !== void 0 || ast.having !== void 0) {
|
|
2532
|
+
const aggregateNode = {
|
|
2533
|
+
aggregates: aggregateExpressions,
|
|
2534
|
+
groupBy: ast.groupBy?.fields ?? [],
|
|
2535
|
+
id: nextPlanNodeId(),
|
|
2536
|
+
input: node,
|
|
2537
|
+
op: "aggregate"
|
|
2538
|
+
};
|
|
2539
|
+
node = ast.having === void 0 ? aggregateNode : { ...aggregateNode, having: ast.having };
|
|
2214
2540
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2541
|
+
if (ast.orderBy !== void 0 && ast.orderBy.length > 0) {
|
|
2542
|
+
node = {
|
|
2543
|
+
id: nextPlanNodeId(),
|
|
2544
|
+
input: node,
|
|
2545
|
+
op: "sort",
|
|
2546
|
+
orderBy: ast.orderBy
|
|
2547
|
+
};
|
|
2219
2548
|
}
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
}
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
case "embedding":
|
|
2243
|
-
case "unknown":
|
|
2244
|
-
case void 0: {
|
|
2245
|
-
return fallback === "text" ? dialect.jsonExtractText(column, pointer) : dialect.jsonExtract(column, pointer);
|
|
2246
|
-
}
|
|
2247
|
-
default: {
|
|
2248
|
-
return fallback === "text" ? dialect.jsonExtractText(column, pointer) : dialect.jsonExtract(column, pointer);
|
|
2549
|
+
if (limit !== void 0 || ast.offset !== void 0) {
|
|
2550
|
+
const limitOffsetNodeBase = {
|
|
2551
|
+
id: nextPlanNodeId(),
|
|
2552
|
+
input: node,
|
|
2553
|
+
op: "limit_offset"
|
|
2554
|
+
};
|
|
2555
|
+
const hasLimit = limit !== void 0;
|
|
2556
|
+
const hasOffset = ast.offset !== void 0;
|
|
2557
|
+
if (hasLimit && hasOffset) {
|
|
2558
|
+
node = {
|
|
2559
|
+
...limitOffsetNodeBase,
|
|
2560
|
+
limit,
|
|
2561
|
+
offset: ast.offset
|
|
2562
|
+
};
|
|
2563
|
+
} else if (hasLimit) {
|
|
2564
|
+
node = { ...limitOffsetNodeBase, limit };
|
|
2565
|
+
} else if (hasOffset) {
|
|
2566
|
+
node = { ...limitOffsetNodeBase, offset: ast.offset };
|
|
2567
|
+
} else {
|
|
2568
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2569
|
+
"limit_offset node requires limit or offset to be present"
|
|
2570
|
+
);
|
|
2249
2571
|
}
|
|
2250
2572
|
}
|
|
2573
|
+
const projectNodeBase = {
|
|
2574
|
+
fields: ast.projection.fields,
|
|
2575
|
+
id: nextPlanNodeId(),
|
|
2576
|
+
input: node,
|
|
2577
|
+
op: "project"
|
|
2578
|
+
};
|
|
2579
|
+
return collapsedTraversalCteAlias === void 0 ? projectNodeBase : {
|
|
2580
|
+
...projectNodeBase,
|
|
2581
|
+
collapsedTraversalAlias: collapsedTraversalCteAlias
|
|
2582
|
+
};
|
|
2251
2583
|
}
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2584
|
+
function lowerStandardQueryToLogicalPlanNode(input) {
|
|
2585
|
+
const { ast, nextPlanNodeId } = input;
|
|
2586
|
+
let currentNode = {
|
|
2587
|
+
alias: ast.start.alias,
|
|
2588
|
+
graphId: input.graphId,
|
|
2589
|
+
id: nextPlanNodeId(),
|
|
2590
|
+
kinds: ast.start.kinds,
|
|
2591
|
+
op: "scan",
|
|
2592
|
+
source: "nodes"
|
|
2593
|
+
};
|
|
2594
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2595
|
+
currentNode,
|
|
2596
|
+
ast,
|
|
2597
|
+
ast.start.alias,
|
|
2598
|
+
"node",
|
|
2599
|
+
nextPlanNodeId
|
|
2600
|
+
);
|
|
2601
|
+
for (const traversal of ast.traversals) {
|
|
2602
|
+
currentNode = {
|
|
2603
|
+
direction: traversal.direction,
|
|
2604
|
+
edgeAlias: traversal.edgeAlias,
|
|
2605
|
+
edgeKinds: traversal.edgeKinds,
|
|
2606
|
+
id: nextPlanNodeId(),
|
|
2607
|
+
input: currentNode,
|
|
2608
|
+
inverseEdgeKinds: traversal.inverseEdgeKinds ?? [],
|
|
2609
|
+
joinFromAlias: traversal.joinFromAlias,
|
|
2610
|
+
joinType: traversal.optional ? "left" : "inner",
|
|
2611
|
+
nodeAlias: traversal.nodeAlias,
|
|
2612
|
+
nodeKinds: traversal.nodeKinds,
|
|
2613
|
+
op: "join"
|
|
2614
|
+
};
|
|
2615
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2616
|
+
currentNode,
|
|
2617
|
+
ast,
|
|
2618
|
+
traversal.edgeAlias,
|
|
2619
|
+
"edge",
|
|
2620
|
+
nextPlanNodeId
|
|
2621
|
+
);
|
|
2622
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2623
|
+
currentNode,
|
|
2624
|
+
ast,
|
|
2625
|
+
traversal.nodeAlias,
|
|
2626
|
+
"node",
|
|
2627
|
+
nextPlanNodeId
|
|
2628
|
+
);
|
|
2629
|
+
}
|
|
2630
|
+
if (input.vectorPredicate !== void 0) {
|
|
2631
|
+
currentNode = {
|
|
2632
|
+
id: nextPlanNodeId(),
|
|
2633
|
+
input: currentNode,
|
|
2634
|
+
op: "vector_knn",
|
|
2635
|
+
predicate: input.vectorPredicate
|
|
2636
|
+
};
|
|
2637
|
+
}
|
|
2638
|
+
return appendAggregateSortLimitAndProjectNodes(
|
|
2639
|
+
currentNode,
|
|
2640
|
+
ast,
|
|
2641
|
+
nextPlanNodeId,
|
|
2642
|
+
input.effectiveLimit,
|
|
2643
|
+
input.collapsedTraversalCteAlias
|
|
2644
|
+
);
|
|
2278
2645
|
}
|
|
2279
|
-
function
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2646
|
+
function lowerRecursiveQueryToLogicalPlanNode(input) {
|
|
2647
|
+
const { ast, nextPlanNodeId } = input;
|
|
2648
|
+
const traversal = input.traversal ?? runRecursiveTraversalSelectionPass(input.ast);
|
|
2649
|
+
let currentNode = {
|
|
2650
|
+
alias: ast.start.alias,
|
|
2651
|
+
graphId: input.graphId,
|
|
2652
|
+
id: nextPlanNodeId(),
|
|
2653
|
+
kinds: ast.start.kinds,
|
|
2654
|
+
op: "scan",
|
|
2655
|
+
source: "nodes"
|
|
2656
|
+
};
|
|
2657
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2658
|
+
currentNode,
|
|
2659
|
+
ast,
|
|
2660
|
+
ast.start.alias,
|
|
2661
|
+
"node",
|
|
2662
|
+
nextPlanNodeId
|
|
2663
|
+
);
|
|
2664
|
+
currentNode = {
|
|
2665
|
+
edgeAlias: traversal.edgeAlias,
|
|
2666
|
+
edgeKinds: traversal.edgeKinds,
|
|
2667
|
+
id: nextPlanNodeId(),
|
|
2668
|
+
input: currentNode,
|
|
2669
|
+
inverseEdgeKinds: traversal.inverseEdgeKinds ?? [],
|
|
2670
|
+
nodeAlias: traversal.nodeAlias,
|
|
2671
|
+
nodeKinds: traversal.nodeKinds,
|
|
2672
|
+
op: "recursive_expand",
|
|
2673
|
+
traversal: traversal.variableLength
|
|
2674
|
+
};
|
|
2675
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2676
|
+
currentNode,
|
|
2677
|
+
ast,
|
|
2678
|
+
traversal.edgeAlias,
|
|
2679
|
+
"edge",
|
|
2680
|
+
nextPlanNodeId
|
|
2681
|
+
);
|
|
2682
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2683
|
+
currentNode,
|
|
2684
|
+
ast,
|
|
2685
|
+
traversal.nodeAlias,
|
|
2686
|
+
"node",
|
|
2687
|
+
nextPlanNodeId
|
|
2688
|
+
);
|
|
2689
|
+
return appendAggregateSortLimitAndProjectNodes(
|
|
2690
|
+
currentNode,
|
|
2691
|
+
ast,
|
|
2692
|
+
nextPlanNodeId,
|
|
2693
|
+
ast.limit
|
|
2694
|
+
);
|
|
2283
2695
|
}
|
|
2284
|
-
function
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2696
|
+
function lowerComposableQueryToLogicalPlanNode(query, dialect, graphId, nextPlanNodeId) {
|
|
2697
|
+
if ("__type" in query) {
|
|
2698
|
+
return lowerSetOperationToLogicalPlanNode(
|
|
2699
|
+
query,
|
|
2700
|
+
graphId,
|
|
2701
|
+
dialect,
|
|
2702
|
+
nextPlanNodeId
|
|
2703
|
+
);
|
|
2289
2704
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
if (field2 === "toId") return "to_id";
|
|
2300
|
-
if (field2.startsWith("meta.")) {
|
|
2301
|
-
return field2.slice(5).replaceAll(/([A-Z])/g, "_$1").toLowerCase();
|
|
2705
|
+
const hasVariableLengthTraversal2 = query.traversals.some(
|
|
2706
|
+
(traversal) => traversal.variableLength !== void 0
|
|
2707
|
+
);
|
|
2708
|
+
if (hasVariableLengthTraversal2) {
|
|
2709
|
+
return lowerRecursiveQueryToLogicalPlanNode({
|
|
2710
|
+
ast: query,
|
|
2711
|
+
graphId,
|
|
2712
|
+
nextPlanNodeId
|
|
2713
|
+
});
|
|
2302
2714
|
}
|
|
2303
|
-
|
|
2715
|
+
const vectorPredicate = runVectorPredicatePass(
|
|
2716
|
+
query,
|
|
2717
|
+
chunk2WVFEIHR_cjs.getDialect(dialect)
|
|
2718
|
+
).vectorPredicate;
|
|
2719
|
+
const effectiveLimit = resolveVectorAwareLimit(query.limit, vectorPredicate);
|
|
2720
|
+
const loweringInput = {
|
|
2721
|
+
ast: query,
|
|
2722
|
+
graphId,
|
|
2723
|
+
nextPlanNodeId,
|
|
2724
|
+
...effectiveLimit === void 0 ? {} : { effectiveLimit },
|
|
2725
|
+
...vectorPredicate === void 0 ? {} : { vectorPredicate }
|
|
2726
|
+
};
|
|
2727
|
+
return lowerStandardQueryToLogicalPlanNode(loweringInput);
|
|
2304
2728
|
}
|
|
2305
|
-
function
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2729
|
+
function lowerSetOperationToLogicalPlanNode(op, graphId, dialect, nextPlanNodeId) {
|
|
2730
|
+
let currentNode = {
|
|
2731
|
+
id: nextPlanNodeId(),
|
|
2732
|
+
left: lowerComposableQueryToLogicalPlanNode(
|
|
2733
|
+
op.left,
|
|
2734
|
+
dialect,
|
|
2735
|
+
graphId,
|
|
2736
|
+
nextPlanNodeId
|
|
2737
|
+
),
|
|
2738
|
+
op: "set_op",
|
|
2739
|
+
operator: op.operator,
|
|
2740
|
+
right: lowerComposableQueryToLogicalPlanNode(
|
|
2741
|
+
op.right,
|
|
2742
|
+
dialect,
|
|
2743
|
+
graphId,
|
|
2744
|
+
nextPlanNodeId
|
|
2745
|
+
)
|
|
2746
|
+
};
|
|
2747
|
+
if (op.orderBy !== void 0 && op.orderBy.length > 0) {
|
|
2748
|
+
currentNode = {
|
|
2749
|
+
id: nextPlanNodeId(),
|
|
2750
|
+
input: currentNode,
|
|
2751
|
+
op: "sort",
|
|
2752
|
+
orderBy: op.orderBy
|
|
2753
|
+
};
|
|
2313
2754
|
}
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2755
|
+
if (op.limit !== void 0 || op.offset !== void 0) {
|
|
2756
|
+
const limitOffsetBase = {
|
|
2757
|
+
id: nextPlanNodeId(),
|
|
2758
|
+
input: currentNode,
|
|
2759
|
+
op: "limit_offset"
|
|
2760
|
+
};
|
|
2761
|
+
if (op.limit !== void 0 && op.offset !== void 0) {
|
|
2762
|
+
currentNode = { ...limitOffsetBase, limit: op.limit, offset: op.offset };
|
|
2763
|
+
} else if (op.limit === void 0) {
|
|
2764
|
+
currentNode = { ...limitOffsetBase, offset: op.offset };
|
|
2765
|
+
} else {
|
|
2766
|
+
currentNode = { ...limitOffsetBase, limit: op.limit };
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
return currentNode;
|
|
2318
2770
|
}
|
|
2319
|
-
function
|
|
2320
|
-
|
|
2771
|
+
function lowerStandardQueryToLogicalPlan(input) {
|
|
2772
|
+
const nextPlanNodeId = createPlanNodeIdFactory();
|
|
2773
|
+
return {
|
|
2774
|
+
metadata: {
|
|
2775
|
+
dialect: input.dialect,
|
|
2776
|
+
graphId: input.graphId
|
|
2777
|
+
},
|
|
2778
|
+
root: lowerStandardQueryToLogicalPlanNode({
|
|
2779
|
+
...input,
|
|
2780
|
+
nextPlanNodeId
|
|
2781
|
+
})
|
|
2782
|
+
};
|
|
2321
2783
|
}
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2784
|
+
function lowerRecursiveQueryToLogicalPlan(input) {
|
|
2785
|
+
const nextPlanNodeId = createPlanNodeIdFactory();
|
|
2786
|
+
return {
|
|
2787
|
+
metadata: {
|
|
2788
|
+
dialect: input.dialect,
|
|
2789
|
+
graphId: input.graphId
|
|
2790
|
+
},
|
|
2791
|
+
root: lowerRecursiveQueryToLogicalPlanNode({
|
|
2792
|
+
...input,
|
|
2793
|
+
nextPlanNodeId
|
|
2794
|
+
})
|
|
2795
|
+
};
|
|
2329
2796
|
}
|
|
2330
|
-
function
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2797
|
+
function lowerSetOperationToLogicalPlan(input) {
|
|
2798
|
+
const nextPlanNodeId = createPlanNodeIdFactory();
|
|
2799
|
+
return {
|
|
2800
|
+
metadata: {
|
|
2801
|
+
dialect: input.dialect,
|
|
2802
|
+
graphId: input.graphId
|
|
2803
|
+
},
|
|
2804
|
+
root: lowerSetOperationToLogicalPlanNode(
|
|
2805
|
+
input.op,
|
|
2806
|
+
input.graphId,
|
|
2807
|
+
input.dialect,
|
|
2808
|
+
nextPlanNodeId
|
|
2809
|
+
)
|
|
2810
|
+
};
|
|
2336
2811
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2812
|
+
|
|
2813
|
+
// src/query/compiler/recursive.ts
|
|
2814
|
+
var MAX_RECURSIVE_DEPTH = 100;
|
|
2815
|
+
var MAX_EXPLICIT_RECURSIVE_DEPTH = 1e3;
|
|
2816
|
+
var NO_ALWAYS_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
2817
|
+
function runRecursiveQueryPassPipeline(ast, graphId, ctx) {
|
|
2818
|
+
let state = {
|
|
2819
|
+
ast,
|
|
2820
|
+
ctx,
|
|
2821
|
+
graphId,
|
|
2822
|
+
logicalPlan: void 0,
|
|
2823
|
+
requiredColumnsByAlias: void 0,
|
|
2824
|
+
temporalFilterPass: void 0,
|
|
2825
|
+
traversal: void 0
|
|
2826
|
+
};
|
|
2827
|
+
const recursiveTraversalPass = runCompilerPass(state, {
|
|
2828
|
+
name: "recursive_traversal",
|
|
2829
|
+
execute(currentState) {
|
|
2830
|
+
return runRecursiveTraversalSelectionPass(currentState.ast);
|
|
2831
|
+
},
|
|
2832
|
+
update(currentState, traversal) {
|
|
2833
|
+
return {
|
|
2834
|
+
...currentState,
|
|
2835
|
+
traversal
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
});
|
|
2839
|
+
state = recursiveTraversalPass.state;
|
|
2840
|
+
const temporalPass = runCompilerPass(state, {
|
|
2841
|
+
name: "temporal_filters",
|
|
2842
|
+
execute(currentState) {
|
|
2843
|
+
return createTemporalFilterPass(
|
|
2844
|
+
currentState.ast,
|
|
2845
|
+
currentState.ctx.dialect.currentTimestamp()
|
|
2846
|
+
);
|
|
2847
|
+
},
|
|
2848
|
+
update(currentState, temporalFilterPass) {
|
|
2849
|
+
return {
|
|
2850
|
+
...currentState,
|
|
2851
|
+
temporalFilterPass
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
});
|
|
2855
|
+
state = temporalPass.state;
|
|
2856
|
+
const columnPruningPass = runCompilerPass(state, {
|
|
2857
|
+
name: "column_pruning",
|
|
2858
|
+
execute(currentState) {
|
|
2859
|
+
const traversal = currentState.traversal;
|
|
2860
|
+
if (traversal === void 0) {
|
|
2861
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2862
|
+
"Recursive traversal pass did not select traversal"
|
|
2863
|
+
);
|
|
2864
|
+
}
|
|
2865
|
+
return collectRequiredColumnsByAlias(currentState.ast, traversal);
|
|
2866
|
+
},
|
|
2867
|
+
update(currentState, requiredColumnsByAlias) {
|
|
2868
|
+
return {
|
|
2869
|
+
...currentState,
|
|
2870
|
+
requiredColumnsByAlias
|
|
2871
|
+
};
|
|
2872
|
+
}
|
|
2873
|
+
});
|
|
2874
|
+
state = columnPruningPass.state;
|
|
2875
|
+
const logicalPlanPass = runCompilerPass(state, {
|
|
2876
|
+
name: "logical_plan",
|
|
2877
|
+
execute(currentState) {
|
|
2878
|
+
const loweringInput = {
|
|
2879
|
+
ast: currentState.ast,
|
|
2880
|
+
dialect: currentState.ctx.dialect.name,
|
|
2881
|
+
graphId: currentState.graphId,
|
|
2882
|
+
...currentState.traversal === void 0 ? {} : { traversal: currentState.traversal }
|
|
2883
|
+
};
|
|
2884
|
+
return lowerRecursiveQueryToLogicalPlan(loweringInput);
|
|
2885
|
+
},
|
|
2886
|
+
update(currentState, logicalPlan) {
|
|
2887
|
+
return {
|
|
2888
|
+
...currentState,
|
|
2889
|
+
logicalPlan
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
});
|
|
2893
|
+
state = logicalPlanPass.state;
|
|
2894
|
+
return state;
|
|
2343
2895
|
}
|
|
2344
|
-
function
|
|
2345
|
-
const
|
|
2346
|
-
const
|
|
2347
|
-
|
|
2348
|
-
const kindFilter = compileKindFilter(drizzleOrm.sql.raw("kind"), kinds);
|
|
2349
|
-
const temporalFilter = input.temporalFilterPass.forAlias();
|
|
2350
|
-
const cteContext = { ...ctx, cteColumnPrefix: "" };
|
|
2351
|
-
const predicateClauses = compilePredicateClauses(
|
|
2352
|
-
getPredicatesForAlias(predicateIndex, alias, "node"),
|
|
2353
|
-
cteContext
|
|
2354
|
-
);
|
|
2355
|
-
const whereClauses = [
|
|
2356
|
-
drizzleOrm.sql`graph_id = ${graphId}`,
|
|
2357
|
-
kindFilter,
|
|
2358
|
-
temporalFilter,
|
|
2359
|
-
...predicateClauses
|
|
2360
|
-
];
|
|
2361
|
-
const effectiveRequiredColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(alias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
2362
|
-
return drizzleOrm.sql`
|
|
2363
|
-
cte_${drizzleOrm.sql.raw(alias)} AS (
|
|
2364
|
-
SELECT ${drizzleOrm.sql.join(
|
|
2365
|
-
compileNodeSelectColumns(void 0, alias, effectiveRequiredColumns),
|
|
2366
|
-
drizzleOrm.sql`, `
|
|
2367
|
-
)}
|
|
2368
|
-
FROM ${ctx.schema.nodesTable}
|
|
2369
|
-
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
|
|
2370
|
-
)
|
|
2371
|
-
`;
|
|
2896
|
+
function compileVariableLengthQuery(ast, graphId, ctx) {
|
|
2897
|
+
const strategy = ctx.dialect.capabilities.recursiveQueryStrategy;
|
|
2898
|
+
const handler = RECURSIVE_QUERY_STRATEGY_HANDLERS[strategy];
|
|
2899
|
+
return handler(ast, graphId, ctx);
|
|
2372
2900
|
}
|
|
2373
|
-
|
|
2901
|
+
var RECURSIVE_QUERY_STRATEGY_HANDLERS = {
|
|
2902
|
+
recursive_cte: compileVariableLengthQueryWithRecursiveCteStrategy
|
|
2903
|
+
};
|
|
2904
|
+
function compileVariableLengthQueryWithRecursiveCteStrategy(ast, graphId, ctx) {
|
|
2905
|
+
const passState = runRecursiveQueryPassPipeline(ast, graphId, ctx);
|
|
2906
|
+
const { dialect } = ctx;
|
|
2374
2907
|
const {
|
|
2908
|
+
logicalPlan,
|
|
2909
|
+
requiredColumnsByAlias,
|
|
2910
|
+
temporalFilterPass,
|
|
2911
|
+
traversal: vlTraversal
|
|
2912
|
+
} = passState;
|
|
2913
|
+
if (temporalFilterPass === void 0) {
|
|
2914
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2915
|
+
"Temporal filter pass did not initialize temporal state"
|
|
2916
|
+
);
|
|
2917
|
+
}
|
|
2918
|
+
if (logicalPlan === void 0) {
|
|
2919
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2920
|
+
"Logical plan pass did not initialize plan state"
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
if (vlTraversal === void 0) {
|
|
2924
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2925
|
+
"Recursive traversal pass did not select traversal"
|
|
2926
|
+
);
|
|
2927
|
+
}
|
|
2928
|
+
const recursiveCte = compileRecursiveCte(
|
|
2375
2929
|
ast,
|
|
2376
|
-
|
|
2377
|
-
ctx,
|
|
2930
|
+
vlTraversal,
|
|
2378
2931
|
graphId,
|
|
2379
|
-
|
|
2380
|
-
predicateIndex,
|
|
2932
|
+
ctx,
|
|
2381
2933
|
requiredColumnsByAlias,
|
|
2382
|
-
temporalFilterPass
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
const
|
|
2387
|
-
const
|
|
2388
|
-
const
|
|
2934
|
+
temporalFilterPass
|
|
2935
|
+
);
|
|
2936
|
+
const projection = compileRecursiveProjection(ast, vlTraversal, dialect);
|
|
2937
|
+
const minDepth = vlTraversal.variableLength.minDepth;
|
|
2938
|
+
const depthFilter = minDepth > 0 ? drizzleOrm.sql`WHERE depth >= ${minDepth}` : drizzleOrm.sql.raw("");
|
|
2939
|
+
const orderBy = compileRecursiveOrderBy(ast, dialect);
|
|
2940
|
+
const limitOffset = compileLimitOffset(ast);
|
|
2941
|
+
return emitRecursiveQuerySql({
|
|
2942
|
+
depthFilter,
|
|
2943
|
+
...limitOffset === void 0 ? {} : { limitOffset },
|
|
2944
|
+
logicalPlan,
|
|
2945
|
+
...orderBy === void 0 ? {} : { orderBy },
|
|
2946
|
+
projection,
|
|
2947
|
+
recursiveCte
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
function hasVariableLengthTraversal(ast) {
|
|
2951
|
+
return ast.traversals.some((t) => t.variableLength !== void 0);
|
|
2952
|
+
}
|
|
2953
|
+
function compileRecursiveCte(ast, traversal, graphId, ctx, requiredColumnsByAlias, temporalFilterPass) {
|
|
2954
|
+
const { dialect } = ctx;
|
|
2955
|
+
const startAlias = ast.start.alias;
|
|
2956
|
+
const startKinds = ast.start.kinds;
|
|
2957
|
+
const nodeAlias = traversal.nodeAlias;
|
|
2389
2958
|
const directEdgeKinds = [...new Set(traversal.edgeKinds)];
|
|
2390
2959
|
const inverseEdgeKinds = traversal.inverseEdgeKinds === void 0 ? [] : [...new Set(traversal.inverseEdgeKinds)];
|
|
2960
|
+
const forceWorktableOuterJoinOrder = dialect.capabilities.forceRecursiveWorktableOuterJoinOrder;
|
|
2391
2961
|
const nodeKinds = traversal.nodeKinds;
|
|
2392
|
-
const
|
|
2962
|
+
const previousNodeKinds = [.../* @__PURE__ */ new Set([...startKinds, ...nodeKinds])];
|
|
2963
|
+
const direction = traversal.direction;
|
|
2964
|
+
const vl = traversal.variableLength;
|
|
2965
|
+
const shouldEnforceCycleCheck = vl.cyclePolicy !== "allow";
|
|
2966
|
+
const shouldTrackPath = shouldEnforceCycleCheck || vl.pathAlias !== void 0;
|
|
2967
|
+
const recursiveJoinRequiredColumns = /* @__PURE__ */ new Set(["id"]);
|
|
2968
|
+
if (previousNodeKinds.length > 1) {
|
|
2969
|
+
recursiveJoinRequiredColumns.add("kind");
|
|
2970
|
+
}
|
|
2971
|
+
const requiredStartColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(startAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
2972
|
+
const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
2973
|
+
const startColumnsFromBase = compileNodeSelectColumnsFromTable(
|
|
2974
|
+
"n0",
|
|
2975
|
+
startAlias,
|
|
2976
|
+
requiredStartColumns,
|
|
2977
|
+
NO_ALWAYS_REQUIRED_COLUMNS
|
|
2978
|
+
);
|
|
2979
|
+
const startColumnsFromRecursive = compileNodeSelectColumnsFromRecursiveRow(
|
|
2980
|
+
startAlias,
|
|
2981
|
+
requiredStartColumns,
|
|
2982
|
+
NO_ALWAYS_REQUIRED_COLUMNS
|
|
2983
|
+
);
|
|
2984
|
+
const nodeColumnsFromBase = compileNodeSelectColumnsFromTable(
|
|
2985
|
+
"n0",
|
|
2986
|
+
nodeAlias,
|
|
2987
|
+
requiredNodeColumns,
|
|
2988
|
+
recursiveJoinRequiredColumns
|
|
2989
|
+
);
|
|
2990
|
+
const nodeColumnsFromRecursive = compileNodeSelectColumnsFromTable(
|
|
2991
|
+
"n",
|
|
2992
|
+
nodeAlias,
|
|
2993
|
+
requiredNodeColumns,
|
|
2994
|
+
recursiveJoinRequiredColumns
|
|
2995
|
+
);
|
|
2996
|
+
const startKindFilter = compileKindFilter2(startKinds, "n0.kind");
|
|
2997
|
+
const nodeKindFilter = compileKindFilter2(nodeKinds, "n.kind");
|
|
2998
|
+
const startTemporalFilter = temporalFilterPass.forAlias("n0");
|
|
2393
2999
|
const edgeTemporalFilter = temporalFilterPass.forAlias("e");
|
|
2394
3000
|
const nodeTemporalFilter = temporalFilterPass.forAlias("n");
|
|
2395
|
-
const
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
3001
|
+
const startContext = { ...ctx, cteColumnPrefix: "" };
|
|
3002
|
+
const startPredicates = compileNodePredicates(ast, startAlias, startContext);
|
|
3003
|
+
const edgeContext = { ...ctx, cteColumnPrefix: "e" };
|
|
3004
|
+
const edgePredicates = compileEdgePredicates(
|
|
3005
|
+
ast,
|
|
3006
|
+
traversal.edgeAlias,
|
|
3007
|
+
edgeContext
|
|
2402
3008
|
);
|
|
2403
|
-
const
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
getPredicatesForAlias(predicateIndex, traversal.edgeAlias, "edge"),
|
|
2409
|
-
edgeCteContext
|
|
3009
|
+
const targetContext = { ...ctx, cteColumnPrefix: "n" };
|
|
3010
|
+
const targetNodePredicates = compileNodePredicates(
|
|
3011
|
+
ast,
|
|
3012
|
+
nodeAlias,
|
|
3013
|
+
targetContext
|
|
2410
3014
|
);
|
|
3015
|
+
if (vl.maxDepth > MAX_EXPLICIT_RECURSIVE_DEPTH) {
|
|
3016
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
3017
|
+
`Recursive traversal maxHops(${vl.maxDepth}) exceeds maximum explicit depth of ${MAX_EXPLICIT_RECURSIVE_DEPTH}`
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
const effectiveMaxDepth = vl.maxDepth > 0 ? vl.maxDepth : MAX_RECURSIVE_DEPTH;
|
|
3021
|
+
const maxDepthCondition = drizzleOrm.sql`r.depth < ${effectiveMaxDepth}`;
|
|
3022
|
+
const cycleCheck = shouldEnforceCycleCheck ? dialect.cycleCheck(drizzleOrm.sql.raw("n.id"), drizzleOrm.sql.raw("r.path")) : void 0;
|
|
3023
|
+
const initialPath = shouldTrackPath ? dialect.initializePath(drizzleOrm.sql.raw("n0.id")) : void 0;
|
|
3024
|
+
const pathExtension = shouldTrackPath ? dialect.extendPath(drizzleOrm.sql.raw("r.path"), drizzleOrm.sql.raw("n.id")) : void 0;
|
|
2411
3025
|
const baseWhereClauses = [
|
|
3026
|
+
drizzleOrm.sql`n0.graph_id = ${graphId}`,
|
|
3027
|
+
startKindFilter,
|
|
3028
|
+
startTemporalFilter,
|
|
3029
|
+
...startPredicates
|
|
3030
|
+
];
|
|
3031
|
+
const recursiveBaseWhereClauses = [
|
|
2412
3032
|
drizzleOrm.sql`e.graph_id = ${graphId}`,
|
|
2413
3033
|
nodeKindFilter,
|
|
2414
3034
|
edgeTemporalFilter,
|
|
2415
3035
|
nodeTemporalFilter,
|
|
2416
|
-
|
|
2417
|
-
...edgePredicateClauses
|
|
2418
|
-
];
|
|
2419
|
-
const previousAlias = traversal.joinFromAlias;
|
|
2420
|
-
const edgeAlias = traversal.edgeAlias;
|
|
2421
|
-
const nodeAlias = traversal.nodeAlias;
|
|
2422
|
-
const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
2423
|
-
const requiredEdgeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(edgeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
|
|
2424
|
-
const previousRowColumns = carryForwardPreviousColumns ? [drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.*`] : [
|
|
2425
|
-
drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id AS ${drizzleOrm.sql.raw(previousAlias)}_id`,
|
|
2426
|
-
drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind AS ${drizzleOrm.sql.raw(previousAlias)}_kind`
|
|
2427
|
-
];
|
|
2428
|
-
const selectColumns = [
|
|
2429
|
-
...previousRowColumns,
|
|
2430
|
-
...compileEdgeSelectColumns("e", edgeAlias, requiredEdgeColumns),
|
|
2431
|
-
...compileNodeSelectColumns("n", nodeAlias, requiredNodeColumns)
|
|
3036
|
+
maxDepthCondition
|
|
2432
3037
|
];
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
),
|
|
2442
|
-
|
|
3038
|
+
if (cycleCheck !== void 0) {
|
|
3039
|
+
recursiveBaseWhereClauses.push(cycleCheck);
|
|
3040
|
+
}
|
|
3041
|
+
recursiveBaseWhereClauses.push(...edgePredicates, ...targetNodePredicates);
|
|
3042
|
+
function compileRecursiveBranch2(branch) {
|
|
3043
|
+
const recursiveFilterClauses = [
|
|
3044
|
+
...recursiveBaseWhereClauses,
|
|
3045
|
+
compileKindFilter2(branch.edgeKinds, "e.kind"),
|
|
3046
|
+
compileKindFilter2(previousNodeKinds, `e.${branch.joinKindField}`),
|
|
3047
|
+
compileKindFilter2(nodeKinds, `e.${branch.targetKindField}`)
|
|
2443
3048
|
];
|
|
2444
3049
|
if (branch.duplicateGuard !== void 0) {
|
|
2445
|
-
|
|
3050
|
+
recursiveFilterClauses.push(branch.duplicateGuard);
|
|
2446
3051
|
}
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
3052
|
+
const recursiveSelectColumns = [
|
|
3053
|
+
...startColumnsFromRecursive,
|
|
3054
|
+
...nodeColumnsFromRecursive,
|
|
3055
|
+
drizzleOrm.sql`r.depth + 1 AS depth`
|
|
3056
|
+
];
|
|
3057
|
+
if (pathExtension !== void 0) {
|
|
3058
|
+
recursiveSelectColumns.push(drizzleOrm.sql`${pathExtension} AS path`);
|
|
3059
|
+
}
|
|
3060
|
+
const recursiveJoinClauses = [
|
|
3061
|
+
drizzleOrm.sql`e.${drizzleOrm.sql.raw(branch.joinField)} = r.${drizzleOrm.sql.raw(nodeAlias)}_id`
|
|
3062
|
+
];
|
|
3063
|
+
if (previousNodeKinds.length > 1) {
|
|
3064
|
+
recursiveJoinClauses.push(
|
|
3065
|
+
drizzleOrm.sql`e.${drizzleOrm.sql.raw(branch.joinKindField)} = r.${drizzleOrm.sql.raw(nodeAlias)}_kind`
|
|
3066
|
+
);
|
|
3067
|
+
}
|
|
3068
|
+
if (forceWorktableOuterJoinOrder) {
|
|
3069
|
+
const recursiveWhereClauses = [
|
|
3070
|
+
...recursiveJoinClauses,
|
|
3071
|
+
...recursiveFilterClauses
|
|
3072
|
+
];
|
|
3073
|
+
return drizzleOrm.sql`
|
|
3074
|
+
SELECT ${drizzleOrm.sql.join(recursiveSelectColumns, drizzleOrm.sql`, `)}
|
|
3075
|
+
FROM recursive_cte r
|
|
3076
|
+
CROSS JOIN ${ctx.schema.edgesTable} e
|
|
3077
|
+
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
3078
|
+
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
3079
|
+
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
3080
|
+
WHERE ${drizzleOrm.sql.join(recursiveWhereClauses, drizzleOrm.sql` AND `)}
|
|
3081
|
+
`;
|
|
3082
|
+
}
|
|
3083
|
+
return drizzleOrm.sql`
|
|
3084
|
+
SELECT ${drizzleOrm.sql.join(recursiveSelectColumns, drizzleOrm.sql`, `)}
|
|
3085
|
+
FROM recursive_cte r
|
|
3086
|
+
JOIN ${ctx.schema.edgesTable} e ON ${drizzleOrm.sql.join(recursiveJoinClauses, drizzleOrm.sql` AND `)}
|
|
2452
3087
|
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
2453
3088
|
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
2454
3089
|
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
2455
|
-
WHERE ${drizzleOrm.sql.join(
|
|
3090
|
+
WHERE ${drizzleOrm.sql.join(recursiveFilterClauses, drizzleOrm.sql` AND `)}
|
|
2456
3091
|
`;
|
|
2457
3092
|
}
|
|
2458
|
-
const directJoinField =
|
|
2459
|
-
const directTargetField =
|
|
2460
|
-
const directJoinKindField =
|
|
2461
|
-
const directTargetKindField =
|
|
2462
|
-
const directBranch =
|
|
2463
|
-
edgeKinds: directEdgeKinds,
|
|
3093
|
+
const directJoinField = direction === "out" ? "from_id" : "to_id";
|
|
3094
|
+
const directTargetField = direction === "out" ? "to_id" : "from_id";
|
|
3095
|
+
const directJoinKindField = direction === "out" ? "from_kind" : "to_kind";
|
|
3096
|
+
const directTargetKindField = direction === "out" ? "to_kind" : "from_kind";
|
|
3097
|
+
const directBranch = compileRecursiveBranch2({
|
|
2464
3098
|
joinField: directJoinField,
|
|
2465
|
-
joinKindField: directJoinKindField,
|
|
2466
3099
|
targetField: directTargetField,
|
|
2467
|
-
|
|
3100
|
+
joinKindField: directJoinKindField,
|
|
3101
|
+
targetKindField: directTargetKindField,
|
|
3102
|
+
edgeKinds: directEdgeKinds
|
|
2468
3103
|
});
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
3104
|
+
function compileInverseRecursiveBranch() {
|
|
3105
|
+
const inverseJoinField = direction === "out" ? "to_id" : "from_id";
|
|
3106
|
+
const inverseTargetField = direction === "out" ? "from_id" : "to_id";
|
|
3107
|
+
const inverseJoinKindField = direction === "out" ? "to_kind" : "from_kind";
|
|
3108
|
+
const inverseTargetKindField = direction === "out" ? "from_kind" : "to_kind";
|
|
3109
|
+
const overlappingKinds = inverseEdgeKinds.filter(
|
|
3110
|
+
(kind) => directEdgeKinds.includes(kind)
|
|
3111
|
+
);
|
|
3112
|
+
const duplicateGuard = overlappingKinds.length > 0 ? drizzleOrm.sql`NOT (e.from_id = e.to_id AND ${compileKindFilter2(overlappingKinds, "e.kind")})` : void 0;
|
|
3113
|
+
const inverseBranch = compileRecursiveBranch2({
|
|
3114
|
+
joinField: inverseJoinField,
|
|
3115
|
+
targetField: inverseTargetField,
|
|
3116
|
+
joinKindField: inverseJoinKindField,
|
|
3117
|
+
targetKindField: inverseTargetKindField,
|
|
3118
|
+
edgeKinds: inverseEdgeKinds,
|
|
3119
|
+
duplicateGuard
|
|
3120
|
+
});
|
|
2480
3121
|
return drizzleOrm.sql`
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
3122
|
+
${directBranch}
|
|
3123
|
+
UNION ALL
|
|
3124
|
+
${inverseBranch}
|
|
2484
3125
|
`;
|
|
2485
3126
|
}
|
|
2486
|
-
const
|
|
2487
|
-
const
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
)
|
|
2493
|
-
|
|
2494
|
-
drizzleOrm.sql.raw("e.kind"),
|
|
2495
|
-
overlappingKinds
|
|
2496
|
-
)})` : void 0;
|
|
2497
|
-
const inverseBranch = compileTraversalBranch({
|
|
2498
|
-
duplicateGuard,
|
|
2499
|
-
edgeKinds: inverseEdgeKinds,
|
|
2500
|
-
joinField: inverseJoinField,
|
|
2501
|
-
joinKindField: inverseJoinKindField,
|
|
2502
|
-
targetField: inverseTargetField,
|
|
2503
|
-
targetKindField: inverseTargetKindField
|
|
2504
|
-
});
|
|
2505
|
-
if (traversalLimitValue !== void 0) {
|
|
2506
|
-
return drizzleOrm.sql`
|
|
2507
|
-
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2508
|
-
SELECT * FROM (
|
|
2509
|
-
${directBranch}
|
|
2510
|
-
UNION ALL
|
|
2511
|
-
${inverseBranch}
|
|
2512
|
-
) AS traversal_rows
|
|
2513
|
-
LIMIT ${traversalLimitValue}
|
|
2514
|
-
)
|
|
2515
|
-
`;
|
|
3127
|
+
const recursiveBranchSql = inverseEdgeKinds.length === 0 ? directBranch : compileInverseRecursiveBranch();
|
|
3128
|
+
const baseSelectColumns = [
|
|
3129
|
+
...startColumnsFromBase,
|
|
3130
|
+
...nodeColumnsFromBase,
|
|
3131
|
+
drizzleOrm.sql`0 AS depth`
|
|
3132
|
+
];
|
|
3133
|
+
if (initialPath !== void 0) {
|
|
3134
|
+
baseSelectColumns.push(drizzleOrm.sql`${initialPath} AS path`);
|
|
2516
3135
|
}
|
|
2517
3136
|
return drizzleOrm.sql`
|
|
2518
|
-
|
|
2519
|
-
|
|
3137
|
+
recursive_cte AS (
|
|
3138
|
+
-- Base case: starting nodes
|
|
3139
|
+
SELECT ${drizzleOrm.sql.join(baseSelectColumns, drizzleOrm.sql`, `)}
|
|
3140
|
+
FROM ${ctx.schema.nodesTable} n0
|
|
3141
|
+
WHERE ${drizzleOrm.sql.join(baseWhereClauses, drizzleOrm.sql` AND `)}
|
|
3142
|
+
|
|
2520
3143
|
UNION ALL
|
|
2521
|
-
|
|
3144
|
+
|
|
3145
|
+
-- Recursive case: follow edges
|
|
3146
|
+
${recursiveBranchSql}
|
|
2522
3147
|
)
|
|
2523
3148
|
`;
|
|
2524
3149
|
}
|
|
2525
|
-
function
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
3150
|
+
function compileKindFilter2(kinds, columnExpr) {
|
|
3151
|
+
return compileKindFilter(drizzleOrm.sql.raw(columnExpr), kinds);
|
|
3152
|
+
}
|
|
3153
|
+
function compileNodePredicates(ast, alias, ctx) {
|
|
3154
|
+
return ast.predicates.filter((p) => p.targetAlias === alias && p.targetType !== "edge").map((p) => compilePredicateExpression(p.expression, ctx));
|
|
3155
|
+
}
|
|
3156
|
+
function compileEdgePredicates(ast, edgeAlias, ctx) {
|
|
3157
|
+
return ast.predicates.filter((p) => p.targetAlias === edgeAlias && p.targetType === "edge").map((p) => compilePredicateExpression(p.expression, ctx));
|
|
3158
|
+
}
|
|
3159
|
+
function collectRequiredColumnsByAlias(ast, traversal) {
|
|
3160
|
+
const selectiveFields = ast.selectiveFields;
|
|
3161
|
+
if (selectiveFields === void 0 || selectiveFields.length === 0) {
|
|
3162
|
+
return void 0;
|
|
3163
|
+
}
|
|
3164
|
+
const requiredColumnsByAlias = /* @__PURE__ */ new Map();
|
|
3165
|
+
const previousNodeKinds = [
|
|
3166
|
+
.../* @__PURE__ */ new Set([...ast.start.kinds, ...traversal.nodeKinds])
|
|
3167
|
+
];
|
|
3168
|
+
addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "id");
|
|
3169
|
+
if (previousNodeKinds.length > 1) {
|
|
3170
|
+
addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "kind");
|
|
3171
|
+
}
|
|
3172
|
+
for (const field2 of selectiveFields) {
|
|
3173
|
+
markSelectiveFieldAsRequired(requiredColumnsByAlias, field2);
|
|
3174
|
+
}
|
|
3175
|
+
if (ast.orderBy) {
|
|
3176
|
+
for (const orderSpec of ast.orderBy) {
|
|
3177
|
+
markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
|
|
2551
3178
|
}
|
|
2552
3179
|
}
|
|
3180
|
+
return requiredColumnsByAlias;
|
|
2553
3181
|
}
|
|
2554
|
-
function
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
return compileFieldValue(
|
|
2560
|
-
field2.source,
|
|
2561
|
-
dialect,
|
|
2562
|
-
field2.source.valueType,
|
|
2563
|
-
cteAlias
|
|
3182
|
+
function compileNodeSelectColumnsFromTable(tableAlias, alias, requiredColumns, alwaysRequiredColumns) {
|
|
3183
|
+
return NODE_COLUMNS.filter(
|
|
3184
|
+
(column) => shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
|
|
3185
|
+
).map(
|
|
3186
|
+
(column) => drizzleOrm.sql`${drizzleOrm.sql.raw(tableAlias)}.${drizzleOrm.sql.raw(column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
|
|
2564
3187
|
);
|
|
2565
3188
|
}
|
|
2566
|
-
function
|
|
2567
|
-
|
|
3189
|
+
function compileNodeSelectColumnsFromRecursiveRow(alias, requiredColumns, alwaysRequiredColumns) {
|
|
3190
|
+
return NODE_COLUMNS.filter(
|
|
3191
|
+
(column) => shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
|
|
3192
|
+
).map((column) => {
|
|
3193
|
+
const projected = `${alias}_${column}`;
|
|
3194
|
+
return drizzleOrm.sql`r.${drizzleOrm.sql.raw(projected)} AS ${drizzleOrm.sql.raw(projected)}`;
|
|
3195
|
+
});
|
|
3196
|
+
}
|
|
3197
|
+
function compileRecursiveProjection(ast, traversal, dialect) {
|
|
2568
3198
|
if (ast.selectiveFields && ast.selectiveFields.length > 0) {
|
|
2569
|
-
return
|
|
3199
|
+
return compileRecursiveSelectiveProjection(
|
|
2570
3200
|
ast.selectiveFields,
|
|
2571
|
-
dialect,
|
|
2572
3201
|
ast,
|
|
2573
|
-
|
|
3202
|
+
traversal,
|
|
3203
|
+
dialect
|
|
2574
3204
|
);
|
|
2575
3205
|
}
|
|
2576
|
-
const
|
|
2577
|
-
|
|
2578
|
-
|
|
3206
|
+
const startAlias = ast.start.alias;
|
|
3207
|
+
const nodeAlias = traversal.nodeAlias;
|
|
3208
|
+
const vl = traversal.variableLength;
|
|
3209
|
+
const fields = [
|
|
3210
|
+
// Start alias fields with metadata
|
|
3211
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_id`,
|
|
3212
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_kind`,
|
|
3213
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_props`,
|
|
3214
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_version`,
|
|
3215
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_valid_from`,
|
|
3216
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_valid_to`,
|
|
3217
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_created_at`,
|
|
3218
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_updated_at`,
|
|
3219
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_deleted_at`,
|
|
3220
|
+
// Node alias fields with metadata
|
|
3221
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_id`,
|
|
3222
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_kind`,
|
|
3223
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_props`,
|
|
3224
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_version`,
|
|
3225
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_valid_from`,
|
|
3226
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_valid_to`,
|
|
3227
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_created_at`,
|
|
3228
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_updated_at`,
|
|
3229
|
+
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_deleted_at`
|
|
3230
|
+
];
|
|
3231
|
+
if (vl.depthAlias !== void 0) {
|
|
3232
|
+
fields.push(drizzleOrm.sql`depth AS ${quoteIdentifier(vl.depthAlias)}`);
|
|
2579
3233
|
}
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
return drizzleOrm.sql`${source} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2583
|
-
});
|
|
2584
|
-
return drizzleOrm.sql.join(projectedFields, drizzleOrm.sql`, `);
|
|
2585
|
-
}
|
|
2586
|
-
function compileSelectiveProjection(fields, dialect, ast, collapsedTraversalCteAlias) {
|
|
2587
|
-
const aliasToCte = /* @__PURE__ */ new Map([
|
|
2588
|
-
[ast.start.alias, `cte_${ast.start.alias}`]
|
|
2589
|
-
]);
|
|
2590
|
-
for (const traversal of ast.traversals) {
|
|
2591
|
-
aliasToCte.set(traversal.nodeAlias, `cte_${traversal.nodeAlias}`);
|
|
2592
|
-
aliasToCte.set(traversal.edgeAlias, `cte_${traversal.nodeAlias}`);
|
|
3234
|
+
if (vl.pathAlias !== void 0) {
|
|
3235
|
+
fields.push(drizzleOrm.sql`path AS ${quoteIdentifier(vl.pathAlias)}`);
|
|
2593
3236
|
}
|
|
3237
|
+
return drizzleOrm.sql.join(fields, drizzleOrm.sql`, `);
|
|
3238
|
+
}
|
|
3239
|
+
function compileRecursiveSelectiveProjection(fields, ast, traversal, dialect) {
|
|
3240
|
+
const allowedAliases = /* @__PURE__ */ new Set([ast.start.alias, traversal.nodeAlias]);
|
|
2594
3241
|
const columns = fields.map((field2) => {
|
|
2595
|
-
|
|
3242
|
+
if (!allowedAliases.has(field2.alias)) {
|
|
3243
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
3244
|
+
`Selective projection for recursive traversals does not support alias "${field2.alias}"`
|
|
3245
|
+
);
|
|
3246
|
+
}
|
|
2596
3247
|
if (field2.isSystemField) {
|
|
2597
3248
|
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
2598
|
-
return drizzleOrm.sql`${drizzleOrm.sql.raw(
|
|
3249
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2599
3250
|
}
|
|
2600
|
-
const
|
|
2601
|
-
const column = drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(propsColumn)}`;
|
|
2602
|
-
const pointer = chunkP5CNM325_cjs.jsonPointer([field2.field]);
|
|
3251
|
+
const column = drizzleOrm.sql.raw(`${field2.alias}_props`);
|
|
2603
3252
|
const extracted = compileTypedJsonExtract({
|
|
2604
3253
|
column,
|
|
2605
3254
|
dialect,
|
|
2606
|
-
pointer,
|
|
3255
|
+
pointer: chunkP5CNM325_cjs.jsonPointer([field2.field]),
|
|
2607
3256
|
valueType: field2.valueType
|
|
2608
3257
|
});
|
|
2609
3258
|
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2610
3259
|
});
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
const { ast, collapsedTraversalCteAlias, vectorPredicate } = input;
|
|
2615
|
-
if (collapsedTraversalCteAlias !== void 0) {
|
|
2616
|
-
return drizzleOrm.sql`FROM ${drizzleOrm.sql.raw(collapsedTraversalCteAlias)}`;
|
|
2617
|
-
}
|
|
2618
|
-
const startAlias = ast.start.alias;
|
|
2619
|
-
const fromClause = drizzleOrm.sql`FROM cte_${drizzleOrm.sql.raw(startAlias)}`;
|
|
2620
|
-
const joins = [];
|
|
2621
|
-
for (const traversal of ast.traversals) {
|
|
2622
|
-
const cteAlias = `cte_${traversal.nodeAlias}`;
|
|
2623
|
-
const previousAlias = traversal.joinFromAlias;
|
|
2624
|
-
const joinType = traversal.optional ? "LEFT JOIN" : "INNER JOIN";
|
|
2625
|
-
joins.push(
|
|
2626
|
-
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`
|
|
2627
|
-
);
|
|
3260
|
+
const vl = traversal.variableLength;
|
|
3261
|
+
if (vl.depthAlias !== void 0) {
|
|
3262
|
+
columns.push(drizzleOrm.sql`depth AS ${quoteIdentifier(vl.depthAlias)}`);
|
|
2628
3263
|
}
|
|
2629
|
-
if (
|
|
2630
|
-
|
|
2631
|
-
joins.push(
|
|
2632
|
-
drizzleOrm.sql`INNER JOIN cte_embeddings ON cte_embeddings.node_id = cte_${drizzleOrm.sql.raw(nodeAlias)}.${drizzleOrm.sql.raw(nodeAlias)}_id`
|
|
2633
|
-
);
|
|
3264
|
+
if (vl.pathAlias !== void 0) {
|
|
3265
|
+
columns.push(drizzleOrm.sql`path AS ${quoteIdentifier(vl.pathAlias)}`);
|
|
2634
3266
|
}
|
|
2635
|
-
return
|
|
3267
|
+
return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
|
|
2636
3268
|
}
|
|
2637
|
-
function
|
|
2638
|
-
const { ast, collapsedTraversalCteAlias, dialect } = input;
|
|
3269
|
+
function compileRecursiveOrderBy(ast, dialect) {
|
|
2639
3270
|
if (!ast.orderBy || ast.orderBy.length === 0) {
|
|
2640
3271
|
return void 0;
|
|
2641
3272
|
}
|
|
@@ -2647,13 +3278,7 @@ function buildStandardOrderBy(input) {
|
|
|
2647
3278
|
"Ordering by JSON arrays or objects is not supported"
|
|
2648
3279
|
);
|
|
2649
3280
|
}
|
|
2650
|
-
const
|
|
2651
|
-
const field2 = compileFieldValue(
|
|
2652
|
-
orderSpec.field,
|
|
2653
|
-
dialect,
|
|
2654
|
-
valueType,
|
|
2655
|
-
cteAlias
|
|
2656
|
-
);
|
|
3281
|
+
const field2 = compileFieldValue(orderSpec.field, dialect, valueType);
|
|
2657
3282
|
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
2658
3283
|
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
2659
3284
|
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
@@ -2664,677 +3289,585 @@ function buildStandardOrderBy(input) {
|
|
|
2664
3289
|
}
|
|
2665
3290
|
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
2666
3291
|
}
|
|
2667
|
-
function
|
|
2668
|
-
const
|
|
2669
|
-
|
|
2670
|
-
}
|
|
2671
|
-
function buildStandardGroupBy(input) {
|
|
2672
|
-
const { ast, dialect } = input;
|
|
2673
|
-
if (!ast.groupBy || ast.groupBy.fields.length === 0) {
|
|
2674
|
-
return void 0;
|
|
2675
|
-
}
|
|
2676
|
-
const seenKeys = /* @__PURE__ */ new Set();
|
|
2677
|
-
const allFields = [];
|
|
2678
|
-
for (const projectedField of ast.projection.fields) {
|
|
2679
|
-
if (projectedField.source.__type === "field_ref") {
|
|
2680
|
-
const key = fieldRefKey(projectedField.source);
|
|
2681
|
-
if (!seenKeys.has(key)) {
|
|
2682
|
-
seenKeys.add(key);
|
|
2683
|
-
allFields.push(projectedField.source);
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
}
|
|
2687
|
-
for (const field2 of ast.groupBy.fields) {
|
|
2688
|
-
const key = fieldRefKey(field2);
|
|
2689
|
-
if (!seenKeys.has(key)) {
|
|
2690
|
-
seenKeys.add(key);
|
|
2691
|
-
allFields.push(field2);
|
|
2692
|
-
}
|
|
3292
|
+
function compileLimitOffset(ast) {
|
|
3293
|
+
const parts = [];
|
|
3294
|
+
if (ast.limit !== void 0) {
|
|
3295
|
+
parts.push(drizzleOrm.sql`LIMIT ${ast.limit}`);
|
|
2693
3296
|
}
|
|
2694
|
-
if (
|
|
2695
|
-
|
|
3297
|
+
if (ast.offset !== void 0) {
|
|
3298
|
+
parts.push(drizzleOrm.sql`OFFSET ${ast.offset}`);
|
|
2696
3299
|
}
|
|
2697
|
-
|
|
2698
|
-
(field2) => compileFieldValue(field2, dialect, field2.valueType, `cte_${field2.alias}`)
|
|
2699
|
-
);
|
|
2700
|
-
return drizzleOrm.sql`GROUP BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
3300
|
+
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
2701
3301
|
}
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
3302
|
+
var DEFAULT_TABLE_NAMES = {
|
|
3303
|
+
nodes: "typegraph_nodes",
|
|
3304
|
+
edges: "typegraph_edges",
|
|
3305
|
+
embeddings: "typegraph_node_embeddings"
|
|
3306
|
+
};
|
|
3307
|
+
var MAX_IDENTIFIER_LENGTH = 63;
|
|
3308
|
+
var VALID_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_$]*$/i;
|
|
3309
|
+
function validateTableName(name, label) {
|
|
3310
|
+
if (!name || name.length === 0) {
|
|
3311
|
+
throw new chunk44SXEVF4_cjs.ConfigurationError(`${label} table name cannot be empty`);
|
|
2706
3312
|
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
}
|
|
2710
|
-
function buildStandardEmbeddingsCte(input) {
|
|
2711
|
-
const { ctx, graphId, vectorPredicate } = input;
|
|
2712
|
-
const { dialect } = ctx;
|
|
2713
|
-
const { field: field2, metric, minScore, queryEmbedding } = vectorPredicate;
|
|
2714
|
-
const fieldPath = field2.jsonPointer ? field2.jsonPointer : field2.path.length > 1 && field2.path[0] === "props" ? `/${field2.path.slice(1).join("/")}` : `/${field2.path.join("/")}`;
|
|
2715
|
-
const distanceExpr = dialect.vectorDistance(
|
|
2716
|
-
drizzleOrm.sql.raw("embedding"),
|
|
2717
|
-
queryEmbedding,
|
|
2718
|
-
metric
|
|
2719
|
-
);
|
|
2720
|
-
const conditions = [
|
|
2721
|
-
drizzleOrm.sql`graph_id = ${graphId}`,
|
|
2722
|
-
drizzleOrm.sql`field_path = ${fieldPath}`
|
|
2723
|
-
];
|
|
2724
|
-
if (minScore !== void 0) {
|
|
2725
|
-
conditions.push(
|
|
2726
|
-
compileVectorMinScoreCondition(distanceExpr, metric, minScore)
|
|
3313
|
+
if (name.length > MAX_IDENTIFIER_LENGTH) {
|
|
3314
|
+
throw new chunk44SXEVF4_cjs.ConfigurationError(
|
|
3315
|
+
`${label} table name exceeds maximum length of ${MAX_IDENTIFIER_LENGTH} characters`
|
|
2727
3316
|
);
|
|
2728
3317
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
node_id,
|
|
2734
|
-
${distanceExpr} AS distance,
|
|
2735
|
-
${scoreExpr} AS score
|
|
2736
|
-
FROM ${ctx.schema.embeddingsTable}
|
|
2737
|
-
WHERE ${drizzleOrm.sql.join(conditions, drizzleOrm.sql` AND `)}
|
|
2738
|
-
ORDER BY ${distanceExpr} ASC
|
|
2739
|
-
)
|
|
2740
|
-
`;
|
|
2741
|
-
}
|
|
2742
|
-
function compileVectorScoreExpression(distanceExpr, metric) {
|
|
2743
|
-
switch (metric) {
|
|
2744
|
-
case "cosine": {
|
|
2745
|
-
return drizzleOrm.sql`(1.0 - ${distanceExpr})`;
|
|
2746
|
-
}
|
|
2747
|
-
case "l2":
|
|
2748
|
-
case "inner_product": {
|
|
2749
|
-
return distanceExpr;
|
|
2750
|
-
}
|
|
3318
|
+
if (!VALID_IDENTIFIER_PATTERN.test(name)) {
|
|
3319
|
+
throw new chunk44SXEVF4_cjs.ConfigurationError(
|
|
3320
|
+
`${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.`
|
|
3321
|
+
);
|
|
2751
3322
|
}
|
|
2752
3323
|
}
|
|
2753
|
-
function
|
|
2754
|
-
|
|
2755
|
-
case "cosine": {
|
|
2756
|
-
const threshold = 1 - minScore;
|
|
2757
|
-
return drizzleOrm.sql`${distanceExpr} <= ${threshold}`;
|
|
2758
|
-
}
|
|
2759
|
-
case "l2": {
|
|
2760
|
-
return drizzleOrm.sql`${distanceExpr} <= ${minScore}`;
|
|
2761
|
-
}
|
|
2762
|
-
case "inner_product": {
|
|
2763
|
-
const negativeThreshold = -minScore;
|
|
2764
|
-
return drizzleOrm.sql`${distanceExpr} <= ${negativeThreshold}`;
|
|
2765
|
-
}
|
|
2766
|
-
}
|
|
3324
|
+
function quoteIdentifier2(name) {
|
|
3325
|
+
return `"${name.replaceAll('"', '""')}"`;
|
|
2767
3326
|
}
|
|
2768
|
-
function
|
|
2769
|
-
const {
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
}
|
|
2780
|
-
const cteAlias = `cte_${orderSpec.field.alias}`;
|
|
2781
|
-
const field2 = compileFieldValue(
|
|
2782
|
-
orderSpec.field,
|
|
2783
|
-
dialect,
|
|
2784
|
-
valueType,
|
|
2785
|
-
cteAlias
|
|
2786
|
-
);
|
|
2787
|
-
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
2788
|
-
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
2789
|
-
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
2790
|
-
additionalOrders.push(
|
|
2791
|
-
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
2792
|
-
drizzleOrm.sql`${field2} ${direction}`
|
|
2793
|
-
);
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
const allOrders = [distanceOrder, ...additionalOrders];
|
|
2797
|
-
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(allOrders, drizzleOrm.sql`, `)}`;
|
|
3327
|
+
function createSqlSchema(names = {}) {
|
|
3328
|
+
const tables = { ...DEFAULT_TABLE_NAMES, ...names };
|
|
3329
|
+
validateTableName(tables.nodes, "nodes");
|
|
3330
|
+
validateTableName(tables.edges, "edges");
|
|
3331
|
+
validateTableName(tables.embeddings, "embeddings");
|
|
3332
|
+
return {
|
|
3333
|
+
tables,
|
|
3334
|
+
nodesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.nodes)),
|
|
3335
|
+
edgesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.edges)),
|
|
3336
|
+
embeddingsTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.embeddings))
|
|
3337
|
+
};
|
|
2798
3338
|
}
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
3339
|
+
var DEFAULT_SQL_SCHEMA = createSqlSchema();
|
|
3340
|
+
|
|
3341
|
+
// src/query/execution/value-decoder.ts
|
|
3342
|
+
function nullToUndefined(value) {
|
|
3343
|
+
return value === null ? void 0 : value;
|
|
3344
|
+
}
|
|
3345
|
+
function decodeSelectedValue(value, typeInfo) {
|
|
3346
|
+
const normalized = nullToUndefined(value);
|
|
3347
|
+
if (normalized === void 0) return void 0;
|
|
3348
|
+
if (typeInfo === void 0) {
|
|
3349
|
+
return normalized;
|
|
2807
3350
|
}
|
|
2808
|
-
return
|
|
3351
|
+
return decodeByValueType(normalized, typeInfo.valueType);
|
|
2809
3352
|
}
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
temporalFilterPass: void 0,
|
|
2823
|
-
traversal: void 0
|
|
2824
|
-
};
|
|
2825
|
-
const recursiveTraversalPass = runCompilerPass(state, {
|
|
2826
|
-
name: "recursive_traversal",
|
|
2827
|
-
execute(currentState) {
|
|
2828
|
-
return runRecursiveTraversalSelectionPass(currentState.ast);
|
|
2829
|
-
},
|
|
2830
|
-
update(currentState, traversal) {
|
|
2831
|
-
return {
|
|
2832
|
-
...currentState,
|
|
2833
|
-
traversal
|
|
2834
|
-
};
|
|
3353
|
+
function decodeByValueType(value, valueType) {
|
|
3354
|
+
switch (valueType) {
|
|
3355
|
+
case "boolean": {
|
|
3356
|
+
if (typeof value === "boolean") return value;
|
|
3357
|
+
if (typeof value === "number") return value !== 0;
|
|
3358
|
+
if (typeof value === "string") {
|
|
3359
|
+
if (value === "0") return false;
|
|
3360
|
+
if (value === "1") return true;
|
|
3361
|
+
if (value.toLowerCase() === "true") return true;
|
|
3362
|
+
if (value.toLowerCase() === "false") return false;
|
|
3363
|
+
}
|
|
3364
|
+
return Boolean(value);
|
|
2835
3365
|
}
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
currentState.ctx.dialect.currentTimestamp()
|
|
2844
|
-
);
|
|
2845
|
-
},
|
|
2846
|
-
update(currentState, temporalFilterPass) {
|
|
2847
|
-
return {
|
|
2848
|
-
...currentState,
|
|
2849
|
-
temporalFilterPass
|
|
2850
|
-
};
|
|
3366
|
+
case "number": {
|
|
3367
|
+
if (typeof value === "number") return value;
|
|
3368
|
+
if (typeof value === "string") {
|
|
3369
|
+
const parsed = Number(value);
|
|
3370
|
+
return Number.isNaN(parsed) ? value : parsed;
|
|
3371
|
+
}
|
|
3372
|
+
return value;
|
|
2851
3373
|
}
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
const
|
|
2858
|
-
if (
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
3374
|
+
case "array":
|
|
3375
|
+
case "object":
|
|
3376
|
+
case "embedding": {
|
|
3377
|
+
if (typeof value !== "string") return value;
|
|
3378
|
+
const trimmed = value.trim();
|
|
3379
|
+
const looksJson = trimmed.startsWith("[") || trimmed.startsWith("{");
|
|
3380
|
+
if (!looksJson) return value;
|
|
3381
|
+
try {
|
|
3382
|
+
return JSON.parse(trimmed);
|
|
3383
|
+
} catch {
|
|
3384
|
+
return value;
|
|
2862
3385
|
}
|
|
2863
|
-
return collectRequiredColumnsByAlias(currentState.ast, traversal);
|
|
2864
|
-
},
|
|
2865
|
-
update(currentState, requiredColumnsByAlias) {
|
|
2866
|
-
return {
|
|
2867
|
-
...currentState,
|
|
2868
|
-
requiredColumnsByAlias
|
|
2869
|
-
};
|
|
2870
3386
|
}
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
execute(currentState) {
|
|
2876
|
-
const loweringInput = {
|
|
2877
|
-
ast: currentState.ast,
|
|
2878
|
-
dialect: currentState.ctx.dialect.name,
|
|
2879
|
-
graphId: currentState.graphId,
|
|
2880
|
-
...currentState.traversal === void 0 ? {} : { traversal: currentState.traversal }
|
|
2881
|
-
};
|
|
2882
|
-
return lowerRecursiveQueryToLogicalPlan(loweringInput);
|
|
2883
|
-
},
|
|
2884
|
-
update(currentState, logicalPlan) {
|
|
2885
|
-
return {
|
|
2886
|
-
...currentState,
|
|
2887
|
-
logicalPlan
|
|
2888
|
-
};
|
|
3387
|
+
case "string":
|
|
3388
|
+
case "date":
|
|
3389
|
+
case "unknown": {
|
|
3390
|
+
return value;
|
|
2889
3391
|
}
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
}
|
|
2894
|
-
function compileVariableLengthQuery(ast, graphId, ctx) {
|
|
2895
|
-
const strategy = ctx.dialect.capabilities.recursiveQueryStrategy;
|
|
2896
|
-
const handler = RECURSIVE_QUERY_STRATEGY_HANDLERS[strategy];
|
|
2897
|
-
return handler(ast, graphId, ctx);
|
|
3392
|
+
default: {
|
|
3393
|
+
return value;
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
2898
3396
|
}
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
3397
|
+
|
|
3398
|
+
// src/store/reserved-keys.ts
|
|
3399
|
+
var RESERVED_NODE_KEYS2 = /* @__PURE__ */ new Set([
|
|
3400
|
+
"id",
|
|
3401
|
+
"kind",
|
|
3402
|
+
"meta"
|
|
3403
|
+
]);
|
|
3404
|
+
var RESERVED_EDGE_KEYS2 = /* @__PURE__ */ new Set([
|
|
3405
|
+
"id",
|
|
3406
|
+
"kind",
|
|
3407
|
+
"meta",
|
|
3408
|
+
"fromKind",
|
|
3409
|
+
"fromId",
|
|
3410
|
+
"toKind",
|
|
3411
|
+
"toId"
|
|
3412
|
+
]);
|
|
3413
|
+
var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
|
|
3414
|
+
"__proto__",
|
|
3415
|
+
"constructor",
|
|
3416
|
+
"prototype"
|
|
3417
|
+
]);
|
|
3418
|
+
function validateProjectionField(field2, entityType, kind) {
|
|
3419
|
+
const reserved = entityType === "node" ? RESERVED_NODE_KEYS2 : RESERVED_EDGE_KEYS2;
|
|
3420
|
+
if (reserved.has(field2)) {
|
|
3421
|
+
throw new chunk44SXEVF4_cjs.ConfigurationError(
|
|
3422
|
+
`Projection field "${field2}" on ${entityType} kind "${kind}" conflicts with a reserved structural key`,
|
|
3423
|
+
{ field: field2, kind, entityType, reservedKeys: [...reserved] },
|
|
3424
|
+
{
|
|
3425
|
+
suggestion: `Remove "${field2}" from the projection. Structural fields (${[...reserved].join(", ")}) are included automatically when relevant.`
|
|
3426
|
+
}
|
|
2914
3427
|
);
|
|
2915
3428
|
}
|
|
2916
|
-
if (
|
|
2917
|
-
throw new chunk44SXEVF4_cjs.
|
|
2918
|
-
"
|
|
3429
|
+
if (PROTOTYPE_POLLUTION_KEYS.has(field2)) {
|
|
3430
|
+
throw new chunk44SXEVF4_cjs.ConfigurationError(
|
|
3431
|
+
`Projection field "${field2}" on ${entityType} kind "${kind}" is not allowed`,
|
|
3432
|
+
{ field: field2, kind, entityType },
|
|
3433
|
+
{
|
|
3434
|
+
suggestion: `"${field2}" cannot be used as a projection field name.`
|
|
3435
|
+
}
|
|
2919
3436
|
);
|
|
2920
3437
|
}
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
3438
|
+
}
|
|
3439
|
+
function filterReservedKeys(props, reservedKeys) {
|
|
3440
|
+
const filtered = {};
|
|
3441
|
+
for (const [key, value] of Object.entries(props)) {
|
|
3442
|
+
if (!reservedKeys.has(key)) {
|
|
3443
|
+
filtered[key] = value;
|
|
3444
|
+
}
|
|
2925
3445
|
}
|
|
2926
|
-
|
|
2927
|
-
ast,
|
|
2928
|
-
vlTraversal,
|
|
2929
|
-
graphId,
|
|
2930
|
-
ctx,
|
|
2931
|
-
requiredColumnsByAlias,
|
|
2932
|
-
temporalFilterPass
|
|
2933
|
-
);
|
|
2934
|
-
const projection = compileRecursiveProjection(ast, vlTraversal, dialect);
|
|
2935
|
-
const minDepth = vlTraversal.variableLength.minDepth;
|
|
2936
|
-
const depthFilter = minDepth > 0 ? drizzleOrm.sql`WHERE depth >= ${minDepth}` : drizzleOrm.sql.raw("");
|
|
2937
|
-
const orderBy = compileRecursiveOrderBy(ast, dialect);
|
|
2938
|
-
const limitOffset = compileLimitOffset(ast);
|
|
2939
|
-
return emitRecursiveQuerySql({
|
|
2940
|
-
depthFilter,
|
|
2941
|
-
...limitOffset === void 0 ? {} : { limitOffset },
|
|
2942
|
-
logicalPlan,
|
|
2943
|
-
...orderBy === void 0 ? {} : { orderBy },
|
|
2944
|
-
projection,
|
|
2945
|
-
recursiveCte
|
|
2946
|
-
});
|
|
3446
|
+
return filtered;
|
|
2947
3447
|
}
|
|
2948
|
-
|
|
2949
|
-
|
|
3448
|
+
|
|
3449
|
+
// src/store/row-mappers.ts
|
|
3450
|
+
function nullToUndefined2(value) {
|
|
3451
|
+
return value === null ? void 0 : value;
|
|
2950
3452
|
}
|
|
2951
|
-
function
|
|
2952
|
-
const
|
|
2953
|
-
const
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
3453
|
+
function rowToNode(row) {
|
|
3454
|
+
const rawProps = JSON.parse(row.props);
|
|
3455
|
+
const props = filterReservedKeys(rawProps, RESERVED_NODE_KEYS2);
|
|
3456
|
+
return {
|
|
3457
|
+
kind: row.kind,
|
|
3458
|
+
id: row.id,
|
|
3459
|
+
meta: rowToNodeMeta(row),
|
|
3460
|
+
...props
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3463
|
+
function rowToNodeMeta(row) {
|
|
3464
|
+
return {
|
|
3465
|
+
version: row.version,
|
|
3466
|
+
validFrom: nullToUndefined2(row.valid_from),
|
|
3467
|
+
validTo: nullToUndefined2(row.valid_to),
|
|
3468
|
+
createdAt: row.created_at,
|
|
3469
|
+
updatedAt: row.updated_at,
|
|
3470
|
+
deletedAt: nullToUndefined2(row.deleted_at)
|
|
3471
|
+
};
|
|
3472
|
+
}
|
|
3473
|
+
function rowToEdge(row) {
|
|
3474
|
+
const rawProps = JSON.parse(row.props);
|
|
3475
|
+
const props = filterReservedKeys(rawProps, RESERVED_EDGE_KEYS2);
|
|
3476
|
+
return {
|
|
3477
|
+
id: row.id,
|
|
3478
|
+
kind: row.kind,
|
|
3479
|
+
fromKind: row.from_kind,
|
|
3480
|
+
fromId: row.from_id,
|
|
3481
|
+
toKind: row.to_kind,
|
|
3482
|
+
toId: row.to_id,
|
|
3483
|
+
meta: rowToEdgeMeta(row),
|
|
3484
|
+
...props
|
|
3485
|
+
};
|
|
3486
|
+
}
|
|
3487
|
+
function rowToEdgeMeta(row) {
|
|
3488
|
+
return {
|
|
3489
|
+
validFrom: nullToUndefined2(row.valid_from),
|
|
3490
|
+
validTo: nullToUndefined2(row.valid_to),
|
|
3491
|
+
createdAt: row.created_at,
|
|
3492
|
+
updatedAt: row.updated_at,
|
|
3493
|
+
deletedAt: nullToUndefined2(row.deleted_at)
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
// src/store/subgraph.ts
|
|
3498
|
+
var DEFAULT_SUBGRAPH_MAX_DEPTH = 10;
|
|
3499
|
+
var MAX_PG_IDENTIFIER_LENGTH = 63;
|
|
3500
|
+
function fnv1aBase36(input) {
|
|
3501
|
+
let hash = 2166136261;
|
|
3502
|
+
for (const character of input) {
|
|
3503
|
+
const codePoint = character.codePointAt(0);
|
|
3504
|
+
if (codePoint === void 0) continue;
|
|
3505
|
+
hash ^= codePoint;
|
|
3506
|
+
hash = Math.imul(hash, 16777619);
|
|
3507
|
+
}
|
|
3508
|
+
return (hash >>> 0).toString(36);
|
|
3509
|
+
}
|
|
3510
|
+
var TEXT_ENCODER = new TextEncoder();
|
|
3511
|
+
function truncateToBytes(value, maxBytes) {
|
|
3512
|
+
const encoded = TEXT_ENCODER.encode(value);
|
|
3513
|
+
if (encoded.byteLength <= maxBytes) return value;
|
|
3514
|
+
let end = maxBytes;
|
|
3515
|
+
while (end > 0 && encoded[end] >= 128 && encoded[end] < 192) {
|
|
3516
|
+
end--;
|
|
3517
|
+
}
|
|
3518
|
+
return new TextDecoder().decode(encoded.slice(0, end));
|
|
3519
|
+
}
|
|
3520
|
+
function projectionAlias(entityPrefix, kind, field2) {
|
|
3521
|
+
const prefix = entityPrefix === "node" ? "sg_n" : "sg_e";
|
|
3522
|
+
const hash = fnv1aBase36(`${kind}\0${field2}`);
|
|
3523
|
+
const fixedBytes = prefix.length + 1 + 1 + hash.length;
|
|
3524
|
+
const maxKindBytes = MAX_PG_IDENTIFIER_LENGTH - fixedBytes;
|
|
3525
|
+
const truncatedKind = truncateToBytes(kind, maxKindBytes);
|
|
3526
|
+
return `${prefix}_${truncatedKind}_${hash}`;
|
|
3527
|
+
}
|
|
3528
|
+
function normalizeProps(value) {
|
|
3529
|
+
return typeof value === "string" ? value : JSON.stringify(value ?? {});
|
|
3530
|
+
}
|
|
3531
|
+
function defineSubgraphProject(_graph) {
|
|
3532
|
+
return (project) => project;
|
|
3533
|
+
}
|
|
3534
|
+
async function executeSubgraph(params) {
|
|
3535
|
+
const { options } = params;
|
|
3536
|
+
if (options.edges.length === 0) {
|
|
3537
|
+
return { nodes: [], edges: [] };
|
|
2968
3538
|
}
|
|
2969
|
-
const
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
"n0",
|
|
2973
|
-
startAlias,
|
|
2974
|
-
requiredStartColumns,
|
|
2975
|
-
NO_ALWAYS_REQUIRED_COLUMNS
|
|
3539
|
+
const maxDepth = Math.min(
|
|
3540
|
+
options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
|
|
3541
|
+
MAX_RECURSIVE_DEPTH
|
|
2976
3542
|
);
|
|
2977
|
-
const
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
3543
|
+
const ctx = {
|
|
3544
|
+
graphId: params.graphId,
|
|
3545
|
+
rootId: params.rootId,
|
|
3546
|
+
edgeKinds: options.edges,
|
|
3547
|
+
maxDepth,
|
|
3548
|
+
includeKinds: options.includeKinds,
|
|
3549
|
+
excludeRoot: options.excludeRoot ?? false,
|
|
3550
|
+
direction: options.direction ?? "out",
|
|
3551
|
+
cyclePolicy: options.cyclePolicy ?? "prevent",
|
|
3552
|
+
dialect: params.dialect,
|
|
3553
|
+
schema: params.schema ?? DEFAULT_SQL_SCHEMA,
|
|
3554
|
+
backend: params.backend
|
|
3555
|
+
};
|
|
3556
|
+
const schemaIntrospector = getSubgraphSchemaIntrospector(params.graph);
|
|
3557
|
+
const nodeProjectionPlan = buildProjectionPlan(
|
|
3558
|
+
getIncludedNodeKinds(params.graph, options.includeKinds),
|
|
3559
|
+
options.project?.nodes,
|
|
3560
|
+
(kind, field2) => schemaIntrospector.getFieldTypeInfo(kind, field2),
|
|
3561
|
+
"node"
|
|
2981
3562
|
);
|
|
2982
|
-
const
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
3563
|
+
const edgeProjectionPlan = buildProjectionPlan(
|
|
3564
|
+
dedupeStrings(options.edges),
|
|
3565
|
+
options.project?.edges,
|
|
3566
|
+
(kind, field2) => schemaIntrospector.getEdgeFieldTypeInfo(kind, field2),
|
|
3567
|
+
"edge"
|
|
3568
|
+
);
|
|
3569
|
+
const reachableCte = buildReachableCte(ctx);
|
|
3570
|
+
const includedIdsCte = buildIncludedIdsCte(ctx);
|
|
3571
|
+
const [nodeRows, edgeRows] = await Promise.all([
|
|
3572
|
+
fetchSubgraphNodes(ctx, reachableCte, includedIdsCte, nodeProjectionPlan),
|
|
3573
|
+
fetchSubgraphEdges(ctx, reachableCte, includedIdsCte, edgeProjectionPlan)
|
|
3574
|
+
]);
|
|
3575
|
+
const nodes = nodeRows.map(
|
|
3576
|
+
(row) => mapSubgraphNodeRow(row, nodeProjectionPlan)
|
|
2987
3577
|
);
|
|
2988
|
-
const
|
|
2989
|
-
|
|
2990
|
-
nodeAlias,
|
|
2991
|
-
requiredNodeColumns,
|
|
2992
|
-
recursiveJoinRequiredColumns
|
|
3578
|
+
const edges = edgeRows.map(
|
|
3579
|
+
(row) => mapSubgraphEdgeRow(row, edgeProjectionPlan)
|
|
2993
3580
|
);
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
const
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3581
|
+
return {
|
|
3582
|
+
nodes,
|
|
3583
|
+
edges
|
|
3584
|
+
};
|
|
3585
|
+
}
|
|
3586
|
+
var introspectorCache = /* @__PURE__ */ new WeakMap();
|
|
3587
|
+
function getSubgraphSchemaIntrospector(graph) {
|
|
3588
|
+
const cached = introspectorCache.get(graph);
|
|
3589
|
+
if (cached !== void 0) return cached;
|
|
3590
|
+
const nodeKinds = new Map(
|
|
3591
|
+
Object.entries(graph.nodes).map(([kind, definition]) => [
|
|
3592
|
+
kind,
|
|
3593
|
+
{ schema: definition.type.schema }
|
|
3594
|
+
])
|
|
3006
3595
|
);
|
|
3007
|
-
const
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3596
|
+
const edgeKinds = new Map(
|
|
3597
|
+
Object.entries(graph.edges).map(([kind, definition]) => [
|
|
3598
|
+
kind,
|
|
3599
|
+
{ schema: definition.type.schema }
|
|
3600
|
+
])
|
|
3012
3601
|
);
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3602
|
+
const introspector = chunkP5CNM325_cjs.createSchemaIntrospector(nodeKinds, edgeKinds);
|
|
3603
|
+
introspectorCache.set(graph, introspector);
|
|
3604
|
+
return introspector;
|
|
3605
|
+
}
|
|
3606
|
+
function buildProjectionPlan(kinds, projectionMap, resolveFieldType, entityPrefix) {
|
|
3607
|
+
const projectedKinds = /* @__PURE__ */ new Map();
|
|
3608
|
+
const fullKinds = [];
|
|
3609
|
+
for (const kind of kinds) {
|
|
3610
|
+
const selection = projectionMap?.[kind];
|
|
3611
|
+
if (selection === void 0) {
|
|
3612
|
+
fullKinds.push(kind);
|
|
3613
|
+
continue;
|
|
3614
|
+
}
|
|
3615
|
+
projectedKinds.set(
|
|
3616
|
+
kind,
|
|
3617
|
+
buildKindProjectionPlan(kind, selection, resolveFieldType, entityPrefix)
|
|
3016
3618
|
);
|
|
3017
3619
|
}
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
const
|
|
3022
|
-
|
|
3023
|
-
const
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
...startPredicates
|
|
3028
|
-
];
|
|
3029
|
-
const recursiveBaseWhereClauses = [
|
|
3030
|
-
drizzleOrm.sql`e.graph_id = ${graphId}`,
|
|
3031
|
-
nodeKindFilter,
|
|
3032
|
-
edgeTemporalFilter,
|
|
3033
|
-
nodeTemporalFilter,
|
|
3034
|
-
maxDepthCondition
|
|
3035
|
-
];
|
|
3036
|
-
if (cycleCheck !== void 0) {
|
|
3037
|
-
recursiveBaseWhereClauses.push(cycleCheck);
|
|
3038
|
-
}
|
|
3039
|
-
recursiveBaseWhereClauses.push(...edgePredicates, ...targetNodePredicates);
|
|
3040
|
-
function compileRecursiveBranch2(branch) {
|
|
3041
|
-
const recursiveFilterClauses = [
|
|
3042
|
-
...recursiveBaseWhereClauses,
|
|
3043
|
-
compileKindFilter2(branch.edgeKinds, "e.kind"),
|
|
3044
|
-
compileKindFilter2(previousNodeKinds, `e.${branch.joinKindField}`),
|
|
3045
|
-
compileKindFilter2(nodeKinds, `e.${branch.targetKindField}`)
|
|
3046
|
-
];
|
|
3047
|
-
if (branch.duplicateGuard !== void 0) {
|
|
3048
|
-
recursiveFilterClauses.push(branch.duplicateGuard);
|
|
3049
|
-
}
|
|
3050
|
-
const recursiveSelectColumns = [
|
|
3051
|
-
...startColumnsFromRecursive,
|
|
3052
|
-
...nodeColumnsFromRecursive,
|
|
3053
|
-
drizzleOrm.sql`r.depth + 1 AS depth`
|
|
3054
|
-
];
|
|
3055
|
-
if (pathExtension !== void 0) {
|
|
3056
|
-
recursiveSelectColumns.push(drizzleOrm.sql`${pathExtension} AS path`);
|
|
3057
|
-
}
|
|
3058
|
-
const recursiveJoinClauses = [
|
|
3059
|
-
drizzleOrm.sql`e.${drizzleOrm.sql.raw(branch.joinField)} = r.${drizzleOrm.sql.raw(nodeAlias)}_id`
|
|
3060
|
-
];
|
|
3061
|
-
if (previousNodeKinds.length > 1) {
|
|
3062
|
-
recursiveJoinClauses.push(
|
|
3063
|
-
drizzleOrm.sql`e.${drizzleOrm.sql.raw(branch.joinKindField)} = r.${drizzleOrm.sql.raw(nodeAlias)}_kind`
|
|
3064
|
-
);
|
|
3620
|
+
return { fullKinds, projectedKinds };
|
|
3621
|
+
}
|
|
3622
|
+
function buildKindProjectionPlan(kind, selection, resolveFieldType, entityPrefix) {
|
|
3623
|
+
const propertyFields = /* @__PURE__ */ new Map();
|
|
3624
|
+
let includeMeta = false;
|
|
3625
|
+
for (const field2 of selection) {
|
|
3626
|
+
if (field2 === "meta") {
|
|
3627
|
+
includeMeta = true;
|
|
3628
|
+
continue;
|
|
3065
3629
|
}
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
FROM recursive_cte r
|
|
3074
|
-
CROSS JOIN ${ctx.schema.edgesTable} e
|
|
3075
|
-
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
3076
|
-
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
3077
|
-
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
3078
|
-
WHERE ${drizzleOrm.sql.join(recursiveWhereClauses, drizzleOrm.sql` AND `)}
|
|
3079
|
-
`;
|
|
3630
|
+
validateProjectionField(field2, entityPrefix, kind);
|
|
3631
|
+
if (!propertyFields.has(field2)) {
|
|
3632
|
+
propertyFields.set(field2, {
|
|
3633
|
+
field: field2,
|
|
3634
|
+
outputName: projectionAlias(entityPrefix, kind, field2),
|
|
3635
|
+
typeInfo: resolveFieldType(kind, field2)
|
|
3636
|
+
});
|
|
3080
3637
|
}
|
|
3081
|
-
return drizzleOrm.sql`
|
|
3082
|
-
SELECT ${drizzleOrm.sql.join(recursiveSelectColumns, drizzleOrm.sql`, `)}
|
|
3083
|
-
FROM recursive_cte r
|
|
3084
|
-
JOIN ${ctx.schema.edgesTable} e ON ${drizzleOrm.sql.join(recursiveJoinClauses, drizzleOrm.sql` AND `)}
|
|
3085
|
-
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
3086
|
-
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
3087
|
-
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
3088
|
-
WHERE ${drizzleOrm.sql.join(recursiveFilterClauses, drizzleOrm.sql` AND `)}
|
|
3089
|
-
`;
|
|
3090
|
-
}
|
|
3091
|
-
const directJoinField = direction === "out" ? "from_id" : "to_id";
|
|
3092
|
-
const directTargetField = direction === "out" ? "to_id" : "from_id";
|
|
3093
|
-
const directJoinKindField = direction === "out" ? "from_kind" : "to_kind";
|
|
3094
|
-
const directTargetKindField = direction === "out" ? "to_kind" : "from_kind";
|
|
3095
|
-
const directBranch = compileRecursiveBranch2({
|
|
3096
|
-
joinField: directJoinField,
|
|
3097
|
-
targetField: directTargetField,
|
|
3098
|
-
joinKindField: directJoinKindField,
|
|
3099
|
-
targetKindField: directTargetKindField,
|
|
3100
|
-
edgeKinds: directEdgeKinds
|
|
3101
|
-
});
|
|
3102
|
-
function compileInverseRecursiveBranch() {
|
|
3103
|
-
const inverseJoinField = direction === "out" ? "to_id" : "from_id";
|
|
3104
|
-
const inverseTargetField = direction === "out" ? "from_id" : "to_id";
|
|
3105
|
-
const inverseJoinKindField = direction === "out" ? "to_kind" : "from_kind";
|
|
3106
|
-
const inverseTargetKindField = direction === "out" ? "from_kind" : "to_kind";
|
|
3107
|
-
const overlappingKinds = inverseEdgeKinds.filter(
|
|
3108
|
-
(kind) => directEdgeKinds.includes(kind)
|
|
3109
|
-
);
|
|
3110
|
-
const duplicateGuard = overlappingKinds.length > 0 ? drizzleOrm.sql`NOT (e.from_id = e.to_id AND ${compileKindFilter2(overlappingKinds, "e.kind")})` : void 0;
|
|
3111
|
-
const inverseBranch = compileRecursiveBranch2({
|
|
3112
|
-
joinField: inverseJoinField,
|
|
3113
|
-
targetField: inverseTargetField,
|
|
3114
|
-
joinKindField: inverseJoinKindField,
|
|
3115
|
-
targetKindField: inverseTargetKindField,
|
|
3116
|
-
edgeKinds: inverseEdgeKinds,
|
|
3117
|
-
duplicateGuard
|
|
3118
|
-
});
|
|
3119
|
-
return drizzleOrm.sql`
|
|
3120
|
-
${directBranch}
|
|
3121
|
-
UNION ALL
|
|
3122
|
-
${inverseBranch}
|
|
3123
|
-
`;
|
|
3124
|
-
}
|
|
3125
|
-
const recursiveBranchSql = inverseEdgeKinds.length === 0 ? directBranch : compileInverseRecursiveBranch();
|
|
3126
|
-
const baseSelectColumns = [
|
|
3127
|
-
...startColumnsFromBase,
|
|
3128
|
-
...nodeColumnsFromBase,
|
|
3129
|
-
drizzleOrm.sql`0 AS depth`
|
|
3130
|
-
];
|
|
3131
|
-
if (initialPath !== void 0) {
|
|
3132
|
-
baseSelectColumns.push(drizzleOrm.sql`${initialPath} AS path`);
|
|
3133
3638
|
}
|
|
3134
|
-
return
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
FROM ${ctx.schema.nodesTable} n0
|
|
3139
|
-
WHERE ${drizzleOrm.sql.join(baseWhereClauses, drizzleOrm.sql` AND `)}
|
|
3140
|
-
|
|
3141
|
-
UNION ALL
|
|
3142
|
-
|
|
3143
|
-
-- Recursive case: follow edges
|
|
3144
|
-
${recursiveBranchSql}
|
|
3145
|
-
)
|
|
3146
|
-
`;
|
|
3147
|
-
}
|
|
3148
|
-
function compileKindFilter2(kinds, columnExpr) {
|
|
3149
|
-
return compileKindFilter(drizzleOrm.sql.raw(columnExpr), kinds);
|
|
3639
|
+
return {
|
|
3640
|
+
includeMeta,
|
|
3641
|
+
propertyFields: [...propertyFields.values()]
|
|
3642
|
+
};
|
|
3150
3643
|
}
|
|
3151
|
-
function
|
|
3152
|
-
|
|
3644
|
+
function getIncludedNodeKinds(graph, includeKinds) {
|
|
3645
|
+
if (includeKinds === void 0 || includeKinds.length === 0) {
|
|
3646
|
+
return Object.keys(graph.nodes);
|
|
3647
|
+
}
|
|
3648
|
+
return dedupeStrings(includeKinds);
|
|
3153
3649
|
}
|
|
3154
|
-
function
|
|
3155
|
-
return
|
|
3650
|
+
function dedupeStrings(values) {
|
|
3651
|
+
return [...new Set(values)];
|
|
3156
3652
|
}
|
|
3157
|
-
function
|
|
3158
|
-
const
|
|
3159
|
-
|
|
3160
|
-
|
|
3653
|
+
function buildReachableCte(ctx) {
|
|
3654
|
+
const shouldTrackPath = ctx.cyclePolicy === "prevent";
|
|
3655
|
+
const edgeKindFilter = compileKindFilter(drizzleOrm.sql.raw("e.kind"), ctx.edgeKinds);
|
|
3656
|
+
const initialPath = shouldTrackPath ? ctx.dialect.initializePath(drizzleOrm.sql.raw("n.id")) : void 0;
|
|
3657
|
+
const pathExtension = shouldTrackPath ? ctx.dialect.extendPath(drizzleOrm.sql.raw("r.path"), drizzleOrm.sql.raw("n.id")) : void 0;
|
|
3658
|
+
const cycleCheck = shouldTrackPath ? ctx.dialect.cycleCheck(drizzleOrm.sql.raw("n.id"), drizzleOrm.sql.raw("r.path")) : void 0;
|
|
3659
|
+
const baseColumns = [drizzleOrm.sql`n.id`, drizzleOrm.sql`n.kind`, drizzleOrm.sql`0 AS depth`];
|
|
3660
|
+
if (initialPath !== void 0) {
|
|
3661
|
+
baseColumns.push(drizzleOrm.sql`${initialPath} AS path`);
|
|
3161
3662
|
}
|
|
3162
|
-
const
|
|
3163
|
-
const
|
|
3164
|
-
|
|
3663
|
+
const baseCase = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(baseColumns, drizzleOrm.sql`, `)} FROM ${ctx.schema.nodesTable} n WHERE n.graph_id = ${ctx.graphId} AND n.id = ${ctx.rootId} AND n.deleted_at IS NULL`;
|
|
3664
|
+
const recursiveColumns = [
|
|
3665
|
+
drizzleOrm.sql`n.id`,
|
|
3666
|
+
drizzleOrm.sql`n.kind`,
|
|
3667
|
+
drizzleOrm.sql`r.depth + 1 AS depth`
|
|
3165
3668
|
];
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "kind");
|
|
3669
|
+
if (pathExtension !== void 0) {
|
|
3670
|
+
recursiveColumns.push(drizzleOrm.sql`${pathExtension} AS path`);
|
|
3169
3671
|
}
|
|
3170
|
-
|
|
3171
|
-
|
|
3672
|
+
const recursiveWhereClauses = [
|
|
3673
|
+
drizzleOrm.sql`e.graph_id = ${ctx.graphId}`,
|
|
3674
|
+
edgeKindFilter,
|
|
3675
|
+
drizzleOrm.sql`e.deleted_at IS NULL`,
|
|
3676
|
+
drizzleOrm.sql`n.deleted_at IS NULL`,
|
|
3677
|
+
drizzleOrm.sql`r.depth < ${ctx.maxDepth}`
|
|
3678
|
+
];
|
|
3679
|
+
if (cycleCheck !== void 0) {
|
|
3680
|
+
recursiveWhereClauses.push(cycleCheck);
|
|
3681
|
+
}
|
|
3682
|
+
const forceWorktableOuterJoinOrder = ctx.dialect.capabilities.forceRecursiveWorktableOuterJoinOrder;
|
|
3683
|
+
const recursiveCase = ctx.direction === "both" ? compileBidirectionalBranch({
|
|
3684
|
+
recursiveColumns,
|
|
3685
|
+
whereClauses: recursiveWhereClauses,
|
|
3686
|
+
forceWorktableOuterJoinOrder,
|
|
3687
|
+
schema: ctx.schema
|
|
3688
|
+
}) : compileRecursiveBranch({
|
|
3689
|
+
recursiveColumns,
|
|
3690
|
+
whereClauses: recursiveWhereClauses,
|
|
3691
|
+
joinField: "from_id",
|
|
3692
|
+
targetField: "to_id",
|
|
3693
|
+
targetKindField: "to_kind",
|
|
3694
|
+
forceWorktableOuterJoinOrder,
|
|
3695
|
+
schema: ctx.schema
|
|
3696
|
+
});
|
|
3697
|
+
return drizzleOrm.sql`WITH RECURSIVE reachable AS (${baseCase} UNION ALL ${recursiveCase})`;
|
|
3698
|
+
}
|
|
3699
|
+
function compileRecursiveBranch(params) {
|
|
3700
|
+
const columns = [...params.recursiveColumns];
|
|
3701
|
+
const selectClause = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)}`;
|
|
3702
|
+
const nodeJoin = drizzleOrm.sql`JOIN ${params.schema.nodesTable} n ON n.graph_id = e.graph_id AND n.id = e.${drizzleOrm.sql.raw(params.targetField)} AND n.kind = e.${drizzleOrm.sql.raw(params.targetKindField)}`;
|
|
3703
|
+
if (params.forceWorktableOuterJoinOrder) {
|
|
3704
|
+
const allWhere = [
|
|
3705
|
+
...params.whereClauses,
|
|
3706
|
+
drizzleOrm.sql`e.${drizzleOrm.sql.raw(params.joinField)} = r.id`
|
|
3707
|
+
];
|
|
3708
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r CROSS JOIN ${params.schema.edgesTable} e ${nodeJoin} WHERE ${drizzleOrm.sql.join(allWhere, drizzleOrm.sql` AND `)}`;
|
|
3709
|
+
}
|
|
3710
|
+
const where = [...params.whereClauses];
|
|
3711
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r JOIN ${params.schema.edgesTable} e ON e.${drizzleOrm.sql.raw(params.joinField)} = r.id ${nodeJoin} WHERE ${drizzleOrm.sql.join(where, drizzleOrm.sql` AND `)}`;
|
|
3712
|
+
}
|
|
3713
|
+
function compileBidirectionalBranch(params) {
|
|
3714
|
+
const columns = [...params.recursiveColumns];
|
|
3715
|
+
const selectClause = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)}`;
|
|
3716
|
+
const nodeJoin = drizzleOrm.sql`JOIN ${params.schema.nodesTable} n ON n.graph_id = e.graph_id AND ((e.to_id = r.id AND n.id = e.from_id AND n.kind = e.from_kind) OR (e.from_id = r.id AND n.id = e.to_id AND n.kind = e.to_kind))`;
|
|
3717
|
+
if (params.forceWorktableOuterJoinOrder) {
|
|
3718
|
+
const allWhere = [
|
|
3719
|
+
...params.whereClauses,
|
|
3720
|
+
drizzleOrm.sql`(e.from_id = r.id OR e.to_id = r.id)`
|
|
3721
|
+
];
|
|
3722
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r CROSS JOIN ${params.schema.edgesTable} e ${nodeJoin} WHERE ${drizzleOrm.sql.join(allWhere, drizzleOrm.sql` AND `)}`;
|
|
3723
|
+
}
|
|
3724
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r JOIN ${params.schema.edgesTable} e ON (e.from_id = r.id OR e.to_id = r.id) ${nodeJoin} WHERE ${drizzleOrm.sql.join([...params.whereClauses], drizzleOrm.sql` AND `)}`;
|
|
3725
|
+
}
|
|
3726
|
+
function buildIncludedIdsCte(ctx) {
|
|
3727
|
+
const filters = [];
|
|
3728
|
+
if (ctx.includeKinds !== void 0 && ctx.includeKinds.length > 0) {
|
|
3729
|
+
filters.push(compileKindFilter(drizzleOrm.sql.raw("kind"), ctx.includeKinds));
|
|
3172
3730
|
}
|
|
3173
|
-
if (
|
|
3174
|
-
|
|
3175
|
-
markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
|
|
3176
|
-
}
|
|
3731
|
+
if (ctx.excludeRoot) {
|
|
3732
|
+
filters.push(drizzleOrm.sql`id != ${ctx.rootId}`);
|
|
3177
3733
|
}
|
|
3178
|
-
|
|
3734
|
+
const whereClause = filters.length > 0 ? drizzleOrm.sql` WHERE ${drizzleOrm.sql.join(filters, drizzleOrm.sql` AND `)}` : drizzleOrm.sql``;
|
|
3735
|
+
return drizzleOrm.sql`, included_ids AS (SELECT DISTINCT id FROM reachable${whereClause})`;
|
|
3179
3736
|
}
|
|
3180
|
-
function
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
(
|
|
3185
|
-
|
|
3737
|
+
async function fetchSubgraphNodes(ctx, reachableCte, includedIdsCte, projectionPlan) {
|
|
3738
|
+
const columns = [
|
|
3739
|
+
drizzleOrm.sql`n.kind`,
|
|
3740
|
+
drizzleOrm.sql`n.id`,
|
|
3741
|
+
buildFullPropsColumn("n", projectionPlan),
|
|
3742
|
+
...buildMetadataColumns("n", projectionPlan, [
|
|
3743
|
+
"version",
|
|
3744
|
+
"valid_from",
|
|
3745
|
+
"valid_to",
|
|
3746
|
+
"created_at",
|
|
3747
|
+
"updated_at",
|
|
3748
|
+
"deleted_at"
|
|
3749
|
+
]),
|
|
3750
|
+
...buildProjectedPropertyColumns("n", projectionPlan, ctx.dialect)
|
|
3751
|
+
];
|
|
3752
|
+
const query = drizzleOrm.sql`${reachableCte}${includedIdsCte} SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)} FROM ${ctx.schema.nodesTable} n WHERE n.graph_id = ${ctx.graphId} AND n.id IN (SELECT id FROM included_ids)`;
|
|
3753
|
+
return ctx.backend.execute(query);
|
|
3186
3754
|
}
|
|
3187
|
-
function
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3755
|
+
async function fetchSubgraphEdges(ctx, reachableCte, includedIdsCte, projectionPlan) {
|
|
3756
|
+
const edgeKindFilter = compileKindFilter(drizzleOrm.sql.raw("e.kind"), ctx.edgeKinds);
|
|
3757
|
+
const columns = [
|
|
3758
|
+
drizzleOrm.sql`e.id`,
|
|
3759
|
+
drizzleOrm.sql`e.kind`,
|
|
3760
|
+
drizzleOrm.sql`e.from_kind`,
|
|
3761
|
+
drizzleOrm.sql`e.from_id`,
|
|
3762
|
+
drizzleOrm.sql`e.to_kind`,
|
|
3763
|
+
drizzleOrm.sql`e.to_id`,
|
|
3764
|
+
buildFullPropsColumn("e", projectionPlan),
|
|
3765
|
+
...buildMetadataColumns("e", projectionPlan, [
|
|
3766
|
+
"valid_from",
|
|
3767
|
+
"valid_to",
|
|
3768
|
+
"created_at",
|
|
3769
|
+
"updated_at",
|
|
3770
|
+
"deleted_at"
|
|
3771
|
+
]),
|
|
3772
|
+
...buildProjectedPropertyColumns("e", projectionPlan, ctx.dialect)
|
|
3773
|
+
];
|
|
3774
|
+
const query = drizzleOrm.sql`${reachableCte}${includedIdsCte} SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)} FROM ${ctx.schema.edgesTable} e WHERE e.graph_id = ${ctx.graphId} AND ${edgeKindFilter} AND e.deleted_at IS NULL AND e.from_id IN (SELECT id FROM included_ids) AND e.to_id IN (SELECT id FROM included_ids)`;
|
|
3775
|
+
return ctx.backend.execute(query);
|
|
3194
3776
|
}
|
|
3195
|
-
function
|
|
3196
|
-
if (
|
|
3197
|
-
return
|
|
3198
|
-
ast.selectiveFields,
|
|
3199
|
-
ast,
|
|
3200
|
-
traversal,
|
|
3201
|
-
dialect
|
|
3202
|
-
);
|
|
3777
|
+
function buildMetadataColumns(alias, plan, columns) {
|
|
3778
|
+
if (plan.projectedKinds.size === 0) {
|
|
3779
|
+
return columns.map((col) => drizzleOrm.sql`${drizzleOrm.sql.raw(`${alias}.${col}`)}`);
|
|
3203
3780
|
}
|
|
3204
|
-
const
|
|
3205
|
-
const
|
|
3206
|
-
|
|
3207
|
-
const fields = [
|
|
3208
|
-
// Start alias fields with metadata
|
|
3209
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_id`,
|
|
3210
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_kind`,
|
|
3211
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_props`,
|
|
3212
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_version`,
|
|
3213
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_valid_from`,
|
|
3214
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_valid_to`,
|
|
3215
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_created_at`,
|
|
3216
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_updated_at`,
|
|
3217
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(startAlias)}_deleted_at`,
|
|
3218
|
-
// Node alias fields with metadata
|
|
3219
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_id`,
|
|
3220
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_kind`,
|
|
3221
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_props`,
|
|
3222
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_version`,
|
|
3223
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_valid_from`,
|
|
3224
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_valid_to`,
|
|
3225
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_created_at`,
|
|
3226
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_updated_at`,
|
|
3227
|
-
drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_deleted_at`
|
|
3228
|
-
];
|
|
3229
|
-
if (vl.depthAlias !== void 0) {
|
|
3230
|
-
fields.push(drizzleOrm.sql`depth AS ${quoteIdentifier(vl.depthAlias)}`);
|
|
3781
|
+
const metaKinds = [...plan.fullKinds];
|
|
3782
|
+
for (const [kind, kindPlan] of plan.projectedKinds) {
|
|
3783
|
+
if (kindPlan.includeMeta) metaKinds.push(kind);
|
|
3231
3784
|
}
|
|
3232
|
-
if (
|
|
3233
|
-
|
|
3785
|
+
if (metaKinds.length === 0) {
|
|
3786
|
+
return columns.map((col) => drizzleOrm.sql`NULL AS ${drizzleOrm.sql.raw(col)}`);
|
|
3234
3787
|
}
|
|
3235
|
-
|
|
3788
|
+
if (metaKinds.length === plan.fullKinds.length + plan.projectedKinds.size) {
|
|
3789
|
+
return columns.map((col) => drizzleOrm.sql`${drizzleOrm.sql.raw(`${alias}.${col}`)}`);
|
|
3790
|
+
}
|
|
3791
|
+
const filter = compileKindFilter(drizzleOrm.sql.raw(`${alias}.kind`), metaKinds);
|
|
3792
|
+
return columns.map(
|
|
3793
|
+
(col) => drizzleOrm.sql`CASE WHEN ${filter} THEN ${drizzleOrm.sql.raw(`${alias}.${col}`)} ELSE NULL END AS ${drizzleOrm.sql.raw(col)}`
|
|
3794
|
+
);
|
|
3236
3795
|
}
|
|
3237
|
-
function
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
if (!allowedAliases.has(field2.alias)) {
|
|
3241
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
3242
|
-
`Selective projection for recursive traversals does not support alias "${field2.alias}"`
|
|
3243
|
-
);
|
|
3244
|
-
}
|
|
3245
|
-
if (field2.isSystemField) {
|
|
3246
|
-
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
3247
|
-
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier(field2.outputName)}`;
|
|
3248
|
-
}
|
|
3249
|
-
const column = drizzleOrm.sql.raw(`${field2.alias}_props`);
|
|
3250
|
-
const extracted = compileTypedJsonExtract({
|
|
3251
|
-
column,
|
|
3252
|
-
dialect,
|
|
3253
|
-
pointer: chunkP5CNM325_cjs.jsonPointer([field2.field]),
|
|
3254
|
-
valueType: field2.valueType
|
|
3255
|
-
});
|
|
3256
|
-
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier(field2.outputName)}`;
|
|
3257
|
-
});
|
|
3258
|
-
const vl = traversal.variableLength;
|
|
3259
|
-
if (vl.depthAlias !== void 0) {
|
|
3260
|
-
columns.push(drizzleOrm.sql`depth AS ${quoteIdentifier(vl.depthAlias)}`);
|
|
3796
|
+
function buildFullPropsColumn(alias, plan) {
|
|
3797
|
+
if (plan.projectedKinds.size === 0) {
|
|
3798
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${alias}.props`)} AS props`;
|
|
3261
3799
|
}
|
|
3262
|
-
if (
|
|
3263
|
-
|
|
3800
|
+
if (plan.fullKinds.length === 0) {
|
|
3801
|
+
return drizzleOrm.sql`NULL AS props`;
|
|
3264
3802
|
}
|
|
3265
|
-
|
|
3803
|
+
const filter = compileKindFilter(drizzleOrm.sql.raw(`${alias}.kind`), plan.fullKinds);
|
|
3804
|
+
return drizzleOrm.sql`CASE WHEN ${filter} THEN ${drizzleOrm.sql.raw(`${alias}.props`)} ELSE NULL END AS props`;
|
|
3266
3805
|
}
|
|
3267
|
-
function
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3806
|
+
function buildProjectedPropertyColumns(alias, plan, dialect) {
|
|
3807
|
+
const columns = [];
|
|
3808
|
+
for (const [kind, kindPlan] of plan.projectedKinds.entries()) {
|
|
3809
|
+
for (const fieldPlan of kindPlan.propertyFields) {
|
|
3810
|
+
const extracted = compileTypedJsonExtract({
|
|
3811
|
+
column: drizzleOrm.sql.raw(`${alias}.props`),
|
|
3812
|
+
dialect,
|
|
3813
|
+
pointer: chunkP5CNM325_cjs.jsonPointer([fieldPlan.field]),
|
|
3814
|
+
valueType: fieldPlan.typeInfo?.valueType
|
|
3815
|
+
});
|
|
3816
|
+
columns.push(
|
|
3817
|
+
drizzleOrm.sql`CASE WHEN ${drizzleOrm.sql.raw(alias)}.kind = ${kind} THEN ${extracted} ELSE NULL END AS ${quoteIdentifier(fieldPlan.outputName)}`
|
|
3277
3818
|
);
|
|
3278
3819
|
}
|
|
3279
|
-
const field2 = compileFieldValue(orderSpec.field, dialect, valueType);
|
|
3280
|
-
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
3281
|
-
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
3282
|
-
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
3283
|
-
parts.push(
|
|
3284
|
-
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
3285
|
-
drizzleOrm.sql`${field2} ${direction}`
|
|
3286
|
-
);
|
|
3287
3820
|
}
|
|
3288
|
-
return
|
|
3821
|
+
return columns;
|
|
3289
3822
|
}
|
|
3290
|
-
function
|
|
3291
|
-
const
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
parts.push(drizzleOrm.sql`OFFSET ${ast.offset}`);
|
|
3823
|
+
function applyProjectedFields(target, row, kindPlan) {
|
|
3824
|
+
for (const fieldPlan of kindPlan.propertyFields) {
|
|
3825
|
+
target[fieldPlan.field] = decodeSelectedValue(
|
|
3826
|
+
row[fieldPlan.outputName],
|
|
3827
|
+
fieldPlan.typeInfo
|
|
3828
|
+
);
|
|
3297
3829
|
}
|
|
3298
|
-
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
3299
3830
|
}
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
function validateTableName(name, label) {
|
|
3308
|
-
if (!name || name.length === 0) {
|
|
3309
|
-
throw new chunk44SXEVF4_cjs.ConfigurationError(`${label} table name cannot be empty`);
|
|
3310
|
-
}
|
|
3311
|
-
if (name.length > MAX_IDENTIFIER_LENGTH) {
|
|
3312
|
-
throw new chunk44SXEVF4_cjs.ConfigurationError(
|
|
3313
|
-
`${label} table name exceeds maximum length of ${MAX_IDENTIFIER_LENGTH} characters`
|
|
3314
|
-
);
|
|
3831
|
+
function mapSubgraphNodeRow(row, projectionPlan) {
|
|
3832
|
+
const kindPlan = projectionPlan.projectedKinds.get(row.kind);
|
|
3833
|
+
if (kindPlan === void 0) {
|
|
3834
|
+
return rowToNode({
|
|
3835
|
+
...row,
|
|
3836
|
+
props: normalizeProps(row.props)
|
|
3837
|
+
});
|
|
3315
3838
|
}
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3839
|
+
const projectedNode = {
|
|
3840
|
+
kind: row.kind,
|
|
3841
|
+
id: row.id
|
|
3842
|
+
};
|
|
3843
|
+
if (kindPlan.includeMeta) {
|
|
3844
|
+
projectedNode.meta = rowToNodeMeta(row);
|
|
3845
|
+
}
|
|
3846
|
+
applyProjectedFields(projectedNode, row, kindPlan);
|
|
3847
|
+
return projectedNode;
|
|
3848
|
+
}
|
|
3849
|
+
function mapSubgraphEdgeRow(row, projectionPlan) {
|
|
3850
|
+
const kindPlan = projectionPlan.projectedKinds.get(row.kind);
|
|
3851
|
+
if (kindPlan === void 0) {
|
|
3852
|
+
return rowToEdge({
|
|
3853
|
+
...row,
|
|
3854
|
+
props: normalizeProps(row.props)
|
|
3855
|
+
});
|
|
3320
3856
|
}
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
validateTableName(tables.edges, "edges");
|
|
3329
|
-
validateTableName(tables.embeddings, "embeddings");
|
|
3330
|
-
return {
|
|
3331
|
-
tables,
|
|
3332
|
-
nodesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.nodes)),
|
|
3333
|
-
edgesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.edges)),
|
|
3334
|
-
embeddingsTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.embeddings))
|
|
3857
|
+
const projectedEdge = {
|
|
3858
|
+
id: row.id,
|
|
3859
|
+
kind: row.kind,
|
|
3860
|
+
fromKind: row.from_kind,
|
|
3861
|
+
fromId: row.from_id,
|
|
3862
|
+
toKind: row.to_kind,
|
|
3863
|
+
toId: row.to_id
|
|
3335
3864
|
};
|
|
3865
|
+
if (kindPlan.includeMeta) {
|
|
3866
|
+
projectedEdge.meta = rowToEdgeMeta(row);
|
|
3867
|
+
}
|
|
3868
|
+
applyProjectedFields(projectedEdge, row, kindPlan);
|
|
3869
|
+
return projectedEdge;
|
|
3336
3870
|
}
|
|
3337
|
-
var DEFAULT_SQL_SCHEMA = createSqlSchema();
|
|
3338
3871
|
var OPERATOR_MAP = {
|
|
3339
3872
|
union: "UNION",
|
|
3340
3873
|
unionAll: "UNION ALL",
|
|
@@ -4703,9 +5236,9 @@ function transformPathColumns(rows, state, _dialect) {
|
|
|
4703
5236
|
}
|
|
4704
5237
|
return changed ? result : rows;
|
|
4705
5238
|
}
|
|
4706
|
-
var
|
|
4707
|
-
var
|
|
4708
|
-
function
|
|
5239
|
+
var RESERVED_NODE_KEYS3 = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
|
|
5240
|
+
var RESERVED_EDGE_KEYS3 = /* @__PURE__ */ new Set(["id", "kind", "fromId", "toId", "meta"]);
|
|
5241
|
+
function nullToUndefined3(value) {
|
|
4709
5242
|
return value === null ? void 0 : value;
|
|
4710
5243
|
}
|
|
4711
5244
|
function assignPropsExcludingReserved(target, props, reservedKeys) {
|
|
@@ -4721,13 +5254,13 @@ function buildSelectableNode(row, alias) {
|
|
|
4721
5254
|
const propsRaw = row[`${alias}_props`];
|
|
4722
5255
|
const rawProps = typeof propsRaw === "string" ? JSON.parse(propsRaw) : propsRaw ?? {};
|
|
4723
5256
|
const version = row[`${alias}_version`];
|
|
4724
|
-
const validFrom =
|
|
5257
|
+
const validFrom = nullToUndefined3(
|
|
4725
5258
|
row[`${alias}_valid_from`]
|
|
4726
5259
|
);
|
|
4727
|
-
const validTo =
|
|
5260
|
+
const validTo = nullToUndefined3(row[`${alias}_valid_to`]);
|
|
4728
5261
|
const createdAt = row[`${alias}_created_at`];
|
|
4729
5262
|
const updatedAt = row[`${alias}_updated_at`];
|
|
4730
|
-
const deletedAt =
|
|
5263
|
+
const deletedAt = nullToUndefined3(
|
|
4731
5264
|
row[`${alias}_deleted_at`]
|
|
4732
5265
|
);
|
|
4733
5266
|
const result = {
|
|
@@ -4742,7 +5275,7 @@ function buildSelectableNode(row, alias) {
|
|
|
4742
5275
|
deletedAt
|
|
4743
5276
|
}
|
|
4744
5277
|
};
|
|
4745
|
-
assignPropsExcludingReserved(result, rawProps,
|
|
5278
|
+
assignPropsExcludingReserved(result, rawProps, RESERVED_NODE_KEYS3);
|
|
4746
5279
|
return result;
|
|
4747
5280
|
}
|
|
4748
5281
|
function buildSelectableNodeOrUndefined(row, alias) {
|
|
@@ -4762,13 +5295,13 @@ function buildSelectableEdge(row, alias) {
|
|
|
4762
5295
|
const toId = row[`${alias}_to_id`];
|
|
4763
5296
|
const propsRaw = row[`${alias}_props`];
|
|
4764
5297
|
const rawProps = typeof propsRaw === "string" ? JSON.parse(propsRaw) : propsRaw ?? {};
|
|
4765
|
-
const validFrom =
|
|
5298
|
+
const validFrom = nullToUndefined3(
|
|
4766
5299
|
row[`${alias}_valid_from`]
|
|
4767
5300
|
);
|
|
4768
|
-
const validTo =
|
|
5301
|
+
const validTo = nullToUndefined3(row[`${alias}_valid_to`]);
|
|
4769
5302
|
const createdAt = row[`${alias}_created_at`];
|
|
4770
5303
|
const updatedAt = row[`${alias}_updated_at`];
|
|
4771
|
-
const deletedAt =
|
|
5304
|
+
const deletedAt = nullToUndefined3(
|
|
4772
5305
|
row[`${alias}_deleted_at`]
|
|
4773
5306
|
);
|
|
4774
5307
|
const result = {
|
|
@@ -4784,7 +5317,7 @@ function buildSelectableEdge(row, alias) {
|
|
|
4784
5317
|
deletedAt
|
|
4785
5318
|
}
|
|
4786
5319
|
};
|
|
4787
|
-
assignPropsExcludingReserved(result, rawProps,
|
|
5320
|
+
assignPropsExcludingReserved(result, rawProps, RESERVED_EDGE_KEYS3);
|
|
4788
5321
|
return result;
|
|
4789
5322
|
}
|
|
4790
5323
|
function buildSelectContext(row, startAlias, traversals) {
|
|
@@ -5170,63 +5703,6 @@ function getPlaceholderForValueType(valueType, mode) {
|
|
|
5170
5703
|
}
|
|
5171
5704
|
}
|
|
5172
5705
|
|
|
5173
|
-
// src/query/execution/value-decoder.ts
|
|
5174
|
-
function nullToUndefined2(value) {
|
|
5175
|
-
return value === null ? void 0 : value;
|
|
5176
|
-
}
|
|
5177
|
-
function decodeSelectedValue(value, typeInfo) {
|
|
5178
|
-
const normalized = nullToUndefined2(value);
|
|
5179
|
-
if (normalized === void 0) return void 0;
|
|
5180
|
-
if (typeInfo === void 0) {
|
|
5181
|
-
return normalized;
|
|
5182
|
-
}
|
|
5183
|
-
return decodeByValueType(normalized, typeInfo.valueType);
|
|
5184
|
-
}
|
|
5185
|
-
function decodeByValueType(value, valueType) {
|
|
5186
|
-
switch (valueType) {
|
|
5187
|
-
case "boolean": {
|
|
5188
|
-
if (typeof value === "boolean") return value;
|
|
5189
|
-
if (typeof value === "number") return value !== 0;
|
|
5190
|
-
if (typeof value === "string") {
|
|
5191
|
-
if (value === "0") return false;
|
|
5192
|
-
if (value === "1") return true;
|
|
5193
|
-
if (value.toLowerCase() === "true") return true;
|
|
5194
|
-
if (value.toLowerCase() === "false") return false;
|
|
5195
|
-
}
|
|
5196
|
-
return Boolean(value);
|
|
5197
|
-
}
|
|
5198
|
-
case "number": {
|
|
5199
|
-
if (typeof value === "number") return value;
|
|
5200
|
-
if (typeof value === "string") {
|
|
5201
|
-
const parsed = Number(value);
|
|
5202
|
-
return Number.isNaN(parsed) ? value : parsed;
|
|
5203
|
-
}
|
|
5204
|
-
return value;
|
|
5205
|
-
}
|
|
5206
|
-
case "array":
|
|
5207
|
-
case "object":
|
|
5208
|
-
case "embedding": {
|
|
5209
|
-
if (typeof value !== "string") return value;
|
|
5210
|
-
const trimmed = value.trim();
|
|
5211
|
-
const looksJson = trimmed.startsWith("[") || trimmed.startsWith("{");
|
|
5212
|
-
if (!looksJson) return value;
|
|
5213
|
-
try {
|
|
5214
|
-
return JSON.parse(trimmed);
|
|
5215
|
-
} catch {
|
|
5216
|
-
return value;
|
|
5217
|
-
}
|
|
5218
|
-
}
|
|
5219
|
-
case "string":
|
|
5220
|
-
case "date":
|
|
5221
|
-
case "unknown": {
|
|
5222
|
-
return value;
|
|
5223
|
-
}
|
|
5224
|
-
default: {
|
|
5225
|
-
return value;
|
|
5226
|
-
}
|
|
5227
|
-
}
|
|
5228
|
-
}
|
|
5229
|
-
|
|
5230
5706
|
// src/query/execution/selective-result-mapper.ts
|
|
5231
5707
|
var MissingSelectiveFieldError = class extends Error {
|
|
5232
5708
|
alias;
|
|
@@ -5395,12 +5871,12 @@ function buildRequiredAliasValue(row, plan) {
|
|
|
5395
5871
|
}
|
|
5396
5872
|
};
|
|
5397
5873
|
for (const field2 of plan.systemFields) {
|
|
5398
|
-
base[field2.field] =
|
|
5874
|
+
base[field2.field] = nullToUndefined(row[field2.outputName]);
|
|
5399
5875
|
}
|
|
5400
5876
|
if (plan.metaFields.length > 0) {
|
|
5401
5877
|
const meta = {};
|
|
5402
5878
|
for (const field2 of plan.metaFields) {
|
|
5403
|
-
meta[field2.metaKey] =
|
|
5879
|
+
meta[field2.metaKey] = nullToUndefined(row[field2.outputName]);
|
|
5404
5880
|
}
|
|
5405
5881
|
base.meta = createGuardedProxy(meta, `${plan.alias}.meta`);
|
|
5406
5882
|
}
|
|
@@ -6368,7 +6844,35 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6368
6844
|
return optimizedResult;
|
|
6369
6845
|
}
|
|
6370
6846
|
const compiled = this.compile();
|
|
6371
|
-
const rawRows = await this.#config.backend.execute(compiled);
|
|
6847
|
+
const rawRows = await this.#config.backend.execute(compiled);
|
|
6848
|
+
this.#config.dialect ?? "sqlite";
|
|
6849
|
+
const rows = transformPathColumns(rawRows, this.#state);
|
|
6850
|
+
return mapResults(
|
|
6851
|
+
rows,
|
|
6852
|
+
this.#state.startAlias,
|
|
6853
|
+
this.#state.traversals,
|
|
6854
|
+
this.#selectFn
|
|
6855
|
+
);
|
|
6856
|
+
}
|
|
6857
|
+
/**
|
|
6858
|
+
* Executes the query against a provided backend.
|
|
6859
|
+
*
|
|
6860
|
+
* Used by `store.batch()` to run multiple queries over a single connection
|
|
6861
|
+
* (e.g., within a transaction). The full compile → execute → transform
|
|
6862
|
+
* pipeline runs identically to `execute()`, but against the given backend.
|
|
6863
|
+
*/
|
|
6864
|
+
async executeOn(backend) {
|
|
6865
|
+
if (hasParameterReferences(this.toAst())) {
|
|
6866
|
+
throw new Error(
|
|
6867
|
+
"Query contains param() references. Use .prepare().execute({...}) instead of .execute()."
|
|
6868
|
+
);
|
|
6869
|
+
}
|
|
6870
|
+
const optimizedResult = await this.#tryOptimizedExecutionOn(backend);
|
|
6871
|
+
if (optimizedResult !== void 0) {
|
|
6872
|
+
return optimizedResult;
|
|
6873
|
+
}
|
|
6874
|
+
const compiled = this.compile();
|
|
6875
|
+
const rawRows = await backend.execute(compiled);
|
|
6372
6876
|
this.#config.dialect ?? "sqlite";
|
|
6373
6877
|
const rows = transformPathColumns(rawRows, this.#state);
|
|
6374
6878
|
return mapResults(
|
|
@@ -6430,6 +6934,56 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6430
6934
|
throw error;
|
|
6431
6935
|
}
|
|
6432
6936
|
}
|
|
6937
|
+
/**
|
|
6938
|
+
* Attempts optimized execution against a provided backend.
|
|
6939
|
+
* Mirror of #tryOptimizedExecution but delegates to the given backend.
|
|
6940
|
+
*/
|
|
6941
|
+
async #tryOptimizedExecutionOn(backend) {
|
|
6942
|
+
const selectiveFields = this.#getSelectiveFieldsForExecute();
|
|
6943
|
+
if (selectiveFields === void 0) {
|
|
6944
|
+
return void 0;
|
|
6945
|
+
}
|
|
6946
|
+
let compiled;
|
|
6947
|
+
if (this.#cachedOptimizedCompiled === NOT_COMPUTED) {
|
|
6948
|
+
const baseAst = buildQueryAst(this.#config, this.#state);
|
|
6949
|
+
const selectiveAst = {
|
|
6950
|
+
...baseAst,
|
|
6951
|
+
selectiveFields
|
|
6952
|
+
};
|
|
6953
|
+
compiled = compileQuery(
|
|
6954
|
+
selectiveAst,
|
|
6955
|
+
this.#config.graphId,
|
|
6956
|
+
this.#compileOptions()
|
|
6957
|
+
);
|
|
6958
|
+
this.#cachedOptimizedCompiled = compiled;
|
|
6959
|
+
} else {
|
|
6960
|
+
compiled = this.#cachedOptimizedCompiled;
|
|
6961
|
+
}
|
|
6962
|
+
const rawSelectiveRows = await backend.execute(compiled);
|
|
6963
|
+
this.#config.dialect ?? "sqlite";
|
|
6964
|
+
const rows = transformPathColumns(rawSelectiveRows, this.#state);
|
|
6965
|
+
try {
|
|
6966
|
+
return mapSelectiveResults(
|
|
6967
|
+
rows,
|
|
6968
|
+
this.#state,
|
|
6969
|
+
selectiveFields,
|
|
6970
|
+
this.#config.schemaIntrospector,
|
|
6971
|
+
this.#selectFn
|
|
6972
|
+
);
|
|
6973
|
+
} catch (error) {
|
|
6974
|
+
if (error instanceof MissingSelectiveFieldError) {
|
|
6975
|
+
this.#cachedSelectiveFieldsForExecute = void 0;
|
|
6976
|
+
this.#cachedOptimizedCompiled = NOT_COMPUTED;
|
|
6977
|
+
return void 0;
|
|
6978
|
+
}
|
|
6979
|
+
if (error instanceof chunk44SXEVF4_cjs.UnsupportedPredicateError) {
|
|
6980
|
+
this.#cachedSelectiveFieldsForExecute = void 0;
|
|
6981
|
+
this.#cachedOptimizedCompiled = NOT_COMPUTED;
|
|
6982
|
+
return void 0;
|
|
6983
|
+
}
|
|
6984
|
+
throw error;
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6433
6987
|
#trackSelectFunctionAccesses(tracker) {
|
|
6434
6988
|
const hasOptionalTraversal = this.#state.traversals.some(
|
|
6435
6989
|
(traversal) => traversal.optional
|
|
@@ -6680,7 +7234,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6680
7234
|
throw new MissingSelectiveFieldError(alias, fieldName);
|
|
6681
7235
|
}
|
|
6682
7236
|
const aliasObject2 = this.#getOrCreateAliasObject(cursorContext, alias);
|
|
6683
|
-
aliasObject2[fieldName] =
|
|
7237
|
+
aliasObject2[fieldName] = nullToUndefined(row[outputName2]);
|
|
6684
7238
|
continue;
|
|
6685
7239
|
}
|
|
6686
7240
|
const segments = chunkP5CNM325_cjs.parseJsonPointer(jsonPointer2);
|
|
@@ -8063,6 +8617,29 @@ var UnionableQuery = class _UnionableQuery {
|
|
|
8063
8617
|
}
|
|
8064
8618
|
return rows;
|
|
8065
8619
|
}
|
|
8620
|
+
/**
|
|
8621
|
+
* Executes the combined query against a provided backend.
|
|
8622
|
+
*
|
|
8623
|
+
* Used by `store.batch()` to run multiple queries over a single connection.
|
|
8624
|
+
*/
|
|
8625
|
+
async executeOn(backend) {
|
|
8626
|
+
if (composableQueryHasParameterReferences(this.toAst())) {
|
|
8627
|
+
throw new Error(
|
|
8628
|
+
"Query contains param() references. Use .prepare().execute({...}) instead of .execute()."
|
|
8629
|
+
);
|
|
8630
|
+
}
|
|
8631
|
+
const compiled = this.compile();
|
|
8632
|
+
const rows = await backend.execute(compiled);
|
|
8633
|
+
if (this.#state.selectFn && this.#state.startAlias) {
|
|
8634
|
+
return mapResults(
|
|
8635
|
+
rows,
|
|
8636
|
+
this.#state.startAlias,
|
|
8637
|
+
this.#state.traversals ?? [],
|
|
8638
|
+
this.#state.selectFn
|
|
8639
|
+
);
|
|
8640
|
+
}
|
|
8641
|
+
return rows;
|
|
8642
|
+
}
|
|
8066
8643
|
};
|
|
8067
8644
|
|
|
8068
8645
|
// src/query/builder/aggregates.ts
|
|
@@ -9283,67 +9860,6 @@ async function checkCardinalityConstraint(ctx, edgeKind, cardinality, fromKind,
|
|
|
9283
9860
|
}
|
|
9284
9861
|
}
|
|
9285
9862
|
|
|
9286
|
-
// src/store/row-mappers.ts
|
|
9287
|
-
var RESERVED_NODE_KEYS3 = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
|
|
9288
|
-
function nullToUndefined3(value) {
|
|
9289
|
-
return value === null ? void 0 : value;
|
|
9290
|
-
}
|
|
9291
|
-
function filterReservedKeys(props, reservedKeys) {
|
|
9292
|
-
const filtered = {};
|
|
9293
|
-
for (const [key, value] of Object.entries(props)) {
|
|
9294
|
-
if (!reservedKeys.has(key)) {
|
|
9295
|
-
filtered[key] = value;
|
|
9296
|
-
}
|
|
9297
|
-
}
|
|
9298
|
-
return filtered;
|
|
9299
|
-
}
|
|
9300
|
-
function rowToNode(row) {
|
|
9301
|
-
const rawProps = JSON.parse(row.props);
|
|
9302
|
-
const props = filterReservedKeys(rawProps, RESERVED_NODE_KEYS3);
|
|
9303
|
-
return {
|
|
9304
|
-
kind: row.kind,
|
|
9305
|
-
id: row.id,
|
|
9306
|
-
meta: {
|
|
9307
|
-
version: row.version,
|
|
9308
|
-
validFrom: nullToUndefined3(row.valid_from),
|
|
9309
|
-
validTo: nullToUndefined3(row.valid_to),
|
|
9310
|
-
createdAt: row.created_at,
|
|
9311
|
-
updatedAt: row.updated_at,
|
|
9312
|
-
deletedAt: nullToUndefined3(row.deleted_at)
|
|
9313
|
-
},
|
|
9314
|
-
...props
|
|
9315
|
-
};
|
|
9316
|
-
}
|
|
9317
|
-
var RESERVED_EDGE_KEYS3 = /* @__PURE__ */ new Set([
|
|
9318
|
-
"id",
|
|
9319
|
-
"kind",
|
|
9320
|
-
"meta",
|
|
9321
|
-
"fromKind",
|
|
9322
|
-
"fromId",
|
|
9323
|
-
"toKind",
|
|
9324
|
-
"toId"
|
|
9325
|
-
]);
|
|
9326
|
-
function rowToEdge(row) {
|
|
9327
|
-
const rawProps = JSON.parse(row.props);
|
|
9328
|
-
const props = filterReservedKeys(rawProps, RESERVED_EDGE_KEYS3);
|
|
9329
|
-
return {
|
|
9330
|
-
id: row.id,
|
|
9331
|
-
kind: row.kind,
|
|
9332
|
-
fromKind: row.from_kind,
|
|
9333
|
-
fromId: row.from_id,
|
|
9334
|
-
toKind: row.to_kind,
|
|
9335
|
-
toId: row.to_id,
|
|
9336
|
-
meta: {
|
|
9337
|
-
validFrom: nullToUndefined3(row.valid_from),
|
|
9338
|
-
validTo: nullToUndefined3(row.valid_to),
|
|
9339
|
-
createdAt: row.created_at,
|
|
9340
|
-
updatedAt: row.updated_at,
|
|
9341
|
-
deletedAt: nullToUndefined3(row.deleted_at)
|
|
9342
|
-
},
|
|
9343
|
-
...props
|
|
9344
|
-
};
|
|
9345
|
-
}
|
|
9346
|
-
|
|
9347
9863
|
// src/store/operations/edge-operations.ts
|
|
9348
9864
|
function getEdgeRegistration(graph, kind) {
|
|
9349
9865
|
const registration = graph.edges[kind];
|
|
@@ -11217,142 +11733,6 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11217
11733
|
}
|
|
11218
11734
|
return results;
|
|
11219
11735
|
}
|
|
11220
|
-
var DEFAULT_SUBGRAPH_MAX_DEPTH = 10;
|
|
11221
|
-
function normalizeProps(value) {
|
|
11222
|
-
return typeof value === "string" ? value : JSON.stringify(value ?? {});
|
|
11223
|
-
}
|
|
11224
|
-
async function executeSubgraph(params) {
|
|
11225
|
-
const { options } = params;
|
|
11226
|
-
if (options.edges.length === 0) {
|
|
11227
|
-
return { nodes: [], edges: [] };
|
|
11228
|
-
}
|
|
11229
|
-
const maxDepth = Math.min(
|
|
11230
|
-
options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
|
|
11231
|
-
MAX_RECURSIVE_DEPTH
|
|
11232
|
-
);
|
|
11233
|
-
const ctx = {
|
|
11234
|
-
graphId: params.graphId,
|
|
11235
|
-
rootId: params.rootId,
|
|
11236
|
-
edgeKinds: options.edges,
|
|
11237
|
-
maxDepth,
|
|
11238
|
-
includeKinds: options.includeKinds,
|
|
11239
|
-
excludeRoot: options.excludeRoot ?? false,
|
|
11240
|
-
direction: options.direction ?? "out",
|
|
11241
|
-
cyclePolicy: options.cyclePolicy ?? "prevent",
|
|
11242
|
-
dialect: params.dialect,
|
|
11243
|
-
schema: params.schema ?? DEFAULT_SQL_SCHEMA,
|
|
11244
|
-
backend: params.backend
|
|
11245
|
-
};
|
|
11246
|
-
const reachableCte = buildReachableCte(ctx);
|
|
11247
|
-
const includedIdsCte = buildIncludedIdsCte(ctx);
|
|
11248
|
-
const [nodeRows, edgeRows] = await Promise.all([
|
|
11249
|
-
fetchSubgraphNodes(ctx, reachableCte, includedIdsCte),
|
|
11250
|
-
fetchSubgraphEdges(ctx, reachableCte, includedIdsCte)
|
|
11251
|
-
]);
|
|
11252
|
-
const nodes = nodeRows.map(
|
|
11253
|
-
(row) => rowToNode({ ...row, props: normalizeProps(row.props) })
|
|
11254
|
-
);
|
|
11255
|
-
const edges = edgeRows.map(
|
|
11256
|
-
(row) => rowToEdge({ ...row, props: normalizeProps(row.props) })
|
|
11257
|
-
);
|
|
11258
|
-
return {
|
|
11259
|
-
nodes,
|
|
11260
|
-
edges
|
|
11261
|
-
};
|
|
11262
|
-
}
|
|
11263
|
-
function buildReachableCte(ctx) {
|
|
11264
|
-
const shouldTrackPath = ctx.cyclePolicy === "prevent";
|
|
11265
|
-
const edgeKindFilter = compileKindFilter(drizzleOrm.sql.raw("e.kind"), ctx.edgeKinds);
|
|
11266
|
-
const initialPath = shouldTrackPath ? ctx.dialect.initializePath(drizzleOrm.sql.raw("n.id")) : void 0;
|
|
11267
|
-
const pathExtension = shouldTrackPath ? ctx.dialect.extendPath(drizzleOrm.sql.raw("r.path"), drizzleOrm.sql.raw("n.id")) : void 0;
|
|
11268
|
-
const cycleCheck = shouldTrackPath ? ctx.dialect.cycleCheck(drizzleOrm.sql.raw("n.id"), drizzleOrm.sql.raw("r.path")) : void 0;
|
|
11269
|
-
const baseColumns = [drizzleOrm.sql`n.id`, drizzleOrm.sql`n.kind`, drizzleOrm.sql`0 AS depth`];
|
|
11270
|
-
if (initialPath !== void 0) {
|
|
11271
|
-
baseColumns.push(drizzleOrm.sql`${initialPath} AS path`);
|
|
11272
|
-
}
|
|
11273
|
-
const baseCase = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(baseColumns, drizzleOrm.sql`, `)} FROM ${ctx.schema.nodesTable} n WHERE n.graph_id = ${ctx.graphId} AND n.id = ${ctx.rootId} AND n.deleted_at IS NULL`;
|
|
11274
|
-
const recursiveColumns = [
|
|
11275
|
-
drizzleOrm.sql`n.id`,
|
|
11276
|
-
drizzleOrm.sql`n.kind`,
|
|
11277
|
-
drizzleOrm.sql`r.depth + 1 AS depth`
|
|
11278
|
-
];
|
|
11279
|
-
if (pathExtension !== void 0) {
|
|
11280
|
-
recursiveColumns.push(drizzleOrm.sql`${pathExtension} AS path`);
|
|
11281
|
-
}
|
|
11282
|
-
const recursiveWhereClauses = [
|
|
11283
|
-
drizzleOrm.sql`e.graph_id = ${ctx.graphId}`,
|
|
11284
|
-
edgeKindFilter,
|
|
11285
|
-
drizzleOrm.sql`e.deleted_at IS NULL`,
|
|
11286
|
-
drizzleOrm.sql`n.deleted_at IS NULL`,
|
|
11287
|
-
drizzleOrm.sql`r.depth < ${ctx.maxDepth}`
|
|
11288
|
-
];
|
|
11289
|
-
if (cycleCheck !== void 0) {
|
|
11290
|
-
recursiveWhereClauses.push(cycleCheck);
|
|
11291
|
-
}
|
|
11292
|
-
const forceWorktableOuterJoinOrder = ctx.dialect.capabilities.forceRecursiveWorktableOuterJoinOrder;
|
|
11293
|
-
const recursiveCase = ctx.direction === "both" ? compileBidirectionalBranch({
|
|
11294
|
-
recursiveColumns,
|
|
11295
|
-
whereClauses: recursiveWhereClauses,
|
|
11296
|
-
forceWorktableOuterJoinOrder,
|
|
11297
|
-
schema: ctx.schema
|
|
11298
|
-
}) : compileRecursiveBranch({
|
|
11299
|
-
recursiveColumns,
|
|
11300
|
-
whereClauses: recursiveWhereClauses,
|
|
11301
|
-
joinField: "from_id",
|
|
11302
|
-
targetField: "to_id",
|
|
11303
|
-
targetKindField: "to_kind",
|
|
11304
|
-
forceWorktableOuterJoinOrder,
|
|
11305
|
-
schema: ctx.schema
|
|
11306
|
-
});
|
|
11307
|
-
return drizzleOrm.sql`WITH RECURSIVE reachable AS (${baseCase} UNION ALL ${recursiveCase})`;
|
|
11308
|
-
}
|
|
11309
|
-
function compileRecursiveBranch(params) {
|
|
11310
|
-
const columns = [...params.recursiveColumns];
|
|
11311
|
-
const selectClause = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)}`;
|
|
11312
|
-
const nodeJoin = drizzleOrm.sql`JOIN ${params.schema.nodesTable} n ON n.graph_id = e.graph_id AND n.id = e.${drizzleOrm.sql.raw(params.targetField)} AND n.kind = e.${drizzleOrm.sql.raw(params.targetKindField)}`;
|
|
11313
|
-
if (params.forceWorktableOuterJoinOrder) {
|
|
11314
|
-
const allWhere = [
|
|
11315
|
-
...params.whereClauses,
|
|
11316
|
-
drizzleOrm.sql`e.${drizzleOrm.sql.raw(params.joinField)} = r.id`
|
|
11317
|
-
];
|
|
11318
|
-
return drizzleOrm.sql`${selectClause} FROM reachable r CROSS JOIN ${params.schema.edgesTable} e ${nodeJoin} WHERE ${drizzleOrm.sql.join(allWhere, drizzleOrm.sql` AND `)}`;
|
|
11319
|
-
}
|
|
11320
|
-
const where = [...params.whereClauses];
|
|
11321
|
-
return drizzleOrm.sql`${selectClause} FROM reachable r JOIN ${params.schema.edgesTable} e ON e.${drizzleOrm.sql.raw(params.joinField)} = r.id ${nodeJoin} WHERE ${drizzleOrm.sql.join(where, drizzleOrm.sql` AND `)}`;
|
|
11322
|
-
}
|
|
11323
|
-
function compileBidirectionalBranch(params) {
|
|
11324
|
-
const columns = [...params.recursiveColumns];
|
|
11325
|
-
const selectClause = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)}`;
|
|
11326
|
-
const nodeJoin = drizzleOrm.sql`JOIN ${params.schema.nodesTable} n ON n.graph_id = e.graph_id AND ((e.to_id = r.id AND n.id = e.from_id AND n.kind = e.from_kind) OR (e.from_id = r.id AND n.id = e.to_id AND n.kind = e.to_kind))`;
|
|
11327
|
-
if (params.forceWorktableOuterJoinOrder) {
|
|
11328
|
-
const allWhere = [
|
|
11329
|
-
...params.whereClauses,
|
|
11330
|
-
drizzleOrm.sql`(e.from_id = r.id OR e.to_id = r.id)`
|
|
11331
|
-
];
|
|
11332
|
-
return drizzleOrm.sql`${selectClause} FROM reachable r CROSS JOIN ${params.schema.edgesTable} e ${nodeJoin} WHERE ${drizzleOrm.sql.join(allWhere, drizzleOrm.sql` AND `)}`;
|
|
11333
|
-
}
|
|
11334
|
-
return drizzleOrm.sql`${selectClause} FROM reachable r JOIN ${params.schema.edgesTable} e ON (e.from_id = r.id OR e.to_id = r.id) ${nodeJoin} WHERE ${drizzleOrm.sql.join([...params.whereClauses], drizzleOrm.sql` AND `)}`;
|
|
11335
|
-
}
|
|
11336
|
-
function buildIncludedIdsCte(ctx) {
|
|
11337
|
-
const filters = [];
|
|
11338
|
-
if (ctx.includeKinds !== void 0 && ctx.includeKinds.length > 0) {
|
|
11339
|
-
filters.push(compileKindFilter(drizzleOrm.sql.raw("kind"), ctx.includeKinds));
|
|
11340
|
-
}
|
|
11341
|
-
if (ctx.excludeRoot) {
|
|
11342
|
-
filters.push(drizzleOrm.sql`id != ${ctx.rootId}`);
|
|
11343
|
-
}
|
|
11344
|
-
const whereClause = filters.length > 0 ? drizzleOrm.sql` WHERE ${drizzleOrm.sql.join(filters, drizzleOrm.sql` AND `)}` : drizzleOrm.sql``;
|
|
11345
|
-
return drizzleOrm.sql`, included_ids AS (SELECT DISTINCT id FROM reachable${whereClause})`;
|
|
11346
|
-
}
|
|
11347
|
-
async function fetchSubgraphNodes(ctx, reachableCte, includedIdsCte) {
|
|
11348
|
-
const query = drizzleOrm.sql`${reachableCte}${includedIdsCte} SELECT n.kind, n.id, n.props, n.version, n.valid_from, n.valid_to, n.created_at, n.updated_at, n.deleted_at FROM ${ctx.schema.nodesTable} n WHERE n.graph_id = ${ctx.graphId} AND n.id IN (SELECT id FROM included_ids)`;
|
|
11349
|
-
return ctx.backend.execute(query);
|
|
11350
|
-
}
|
|
11351
|
-
async function fetchSubgraphEdges(ctx, reachableCte, includedIdsCte) {
|
|
11352
|
-
const edgeKindFilter = compileKindFilter(drizzleOrm.sql.raw("e.kind"), ctx.edgeKinds);
|
|
11353
|
-
const query = drizzleOrm.sql`${reachableCte}${includedIdsCte} SELECT e.id, e.kind, e.from_kind, e.from_id, e.to_kind, e.to_id, e.props, e.valid_from, e.valid_to, e.created_at, e.updated_at, e.deleted_at FROM ${ctx.schema.edgesTable} e WHERE e.graph_id = ${ctx.graphId} AND ${edgeKindFilter} AND e.deleted_at IS NULL AND e.from_id IN (SELECT id FROM included_ids) AND e.to_id IN (SELECT id FROM included_ids)`;
|
|
11354
|
-
return ctx.backend.execute(query);
|
|
11355
|
-
}
|
|
11356
11736
|
|
|
11357
11737
|
// src/store/store.ts
|
|
11358
11738
|
var Store = class {
|
|
@@ -11556,6 +11936,46 @@ var Store = class {
|
|
|
11556
11936
|
query() {
|
|
11557
11937
|
return this.#createQueryForBackend(this.#backend);
|
|
11558
11938
|
}
|
|
11939
|
+
// === Batch Query Execution ===
|
|
11940
|
+
/**
|
|
11941
|
+
* Executes multiple queries over a single connection with snapshot consistency.
|
|
11942
|
+
*
|
|
11943
|
+
* Acquires one connection via an implicit transaction, executes each query
|
|
11944
|
+
* sequentially on that connection, and returns a typed tuple of results.
|
|
11945
|
+
* Each query preserves its own result type, projection, filtering,
|
|
11946
|
+
* sorting, and pagination.
|
|
11947
|
+
*
|
|
11948
|
+
* Read-only — use `bulkCreate`, `bulkInsert`, etc. for write batching.
|
|
11949
|
+
*
|
|
11950
|
+
* @example
|
|
11951
|
+
* ```typescript
|
|
11952
|
+
* const [people, companies] = await store.batch(
|
|
11953
|
+
* store.query()
|
|
11954
|
+
* .from("Person", "p")
|
|
11955
|
+
* .select((ctx) => ({ id: ctx.p.id, name: ctx.p.name })),
|
|
11956
|
+
* store.query()
|
|
11957
|
+
* .from("Company", "c")
|
|
11958
|
+
* .select((ctx) => ({ id: ctx.c.id, name: ctx.c.name }))
|
|
11959
|
+
* .orderBy("c", "name", "asc")
|
|
11960
|
+
* .limit(5),
|
|
11961
|
+
* );
|
|
11962
|
+
* // people: readonly { id: string; name: string }[]
|
|
11963
|
+
* // companies: readonly { id: string; name: string }[]
|
|
11964
|
+
* ```
|
|
11965
|
+
*
|
|
11966
|
+
* @param queries - Two or more executable queries (from `.select()` or set operations)
|
|
11967
|
+
* @returns A tuple with per-query typed results, preserving input order
|
|
11968
|
+
*/
|
|
11969
|
+
async batch(...queries) {
|
|
11970
|
+
return this.#backend.transaction(async (txBackend) => {
|
|
11971
|
+
const results = [];
|
|
11972
|
+
for (const query of queries) {
|
|
11973
|
+
const result = await query.executeOn(txBackend);
|
|
11974
|
+
results.push(result);
|
|
11975
|
+
}
|
|
11976
|
+
return results;
|
|
11977
|
+
});
|
|
11978
|
+
}
|
|
11559
11979
|
// === Subgraph Extraction ===
|
|
11560
11980
|
/**
|
|
11561
11981
|
* Extracts a typed subgraph by traversing from a root node.
|
|
@@ -11581,6 +12001,7 @@ var Store = class {
|
|
|
11581
12001
|
*/
|
|
11582
12002
|
async subgraph(rootId, options) {
|
|
11583
12003
|
return executeSubgraph({
|
|
12004
|
+
graph: this.#graph,
|
|
11584
12005
|
graphId: this.graphId,
|
|
11585
12006
|
rootId,
|
|
11586
12007
|
backend: this.#backend,
|
|
@@ -11942,6 +12363,7 @@ exports.createStore = createStore;
|
|
|
11942
12363
|
exports.createStoreWithSchema = createStoreWithSchema;
|
|
11943
12364
|
exports.defineEdge = defineEdge;
|
|
11944
12365
|
exports.defineNode = defineNode;
|
|
12366
|
+
exports.defineSubgraphProject = defineSubgraphProject;
|
|
11945
12367
|
exports.differentFrom = differentFrom;
|
|
11946
12368
|
exports.disjointWith = disjointWith;
|
|
11947
12369
|
exports.equivalentTo = equivalentTo;
|