@nicia-ai/typegraph 0.11.1 → 0.13.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 +2506 -2052
- 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 +2506 -2053
- 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-6-vH0ZIj.d.ts} +169 -8
- package/dist/{store-C01_WsOg.d.cts → store-Bmdt_dS6.d.cts} +169 -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,1878 +1397,2477 @@ 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
|
|
1921
|
+
];
|
|
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
|
+
`;
|
|
2018
|
+
}
|
|
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}`
|
|
2054
2284
|
];
|
|
2055
|
-
if (
|
|
2056
|
-
|
|
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
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
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
|
+
}
|
|
2327
|
+
}
|
|
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}`
|
|
2354
|
+
);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
const allOrders = [distanceOrder, ...additionalOrders];
|
|
2358
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(allOrders, drizzleOrm.sql`, `)}`;
|
|
2359
|
+
}
|
|
2360
|
+
function buildLimitOffsetClause(input) {
|
|
2361
|
+
const { limit, offset } = input;
|
|
2362
|
+
const parts = [];
|
|
2363
|
+
if (limit !== void 0) {
|
|
2364
|
+
parts.push(drizzleOrm.sql`LIMIT ${limit}`);
|
|
2365
|
+
}
|
|
2366
|
+
if (offset !== void 0) {
|
|
2367
|
+
parts.push(drizzleOrm.sql`OFFSET ${offset}`);
|
|
2368
|
+
}
|
|
2369
|
+
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
2370
|
+
}
|
|
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");
|
|
2379
|
+
}
|
|
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."
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
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
|
+
}
|
|
2416
|
+
}
|
|
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"
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
const vectorPredicate = vectorPredicates[0];
|
|
2447
|
+
if (vectorPredicate === void 0) {
|
|
2448
|
+
return { vectorPredicate: void 0 };
|
|
2449
|
+
}
|
|
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}"`
|
|
2454
|
+
);
|
|
2455
|
+
}
|
|
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
|
+
);
|
|
2460
|
+
}
|
|
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
|
+
);
|
|
2465
|
+
}
|
|
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
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
return { vectorPredicate };
|
|
2480
|
+
}
|
|
2481
|
+
function resolveVectorAwareLimit(astLimit, vectorPredicate) {
|
|
2482
|
+
if (vectorPredicate === void 0) {
|
|
2483
|
+
return astLimit;
|
|
2484
|
+
}
|
|
2485
|
+
if (astLimit === void 0) {
|
|
2486
|
+
return vectorPredicate.limit;
|
|
2487
|
+
}
|
|
2488
|
+
return Math.min(astLimit, vectorPredicate.limit);
|
|
2489
|
+
}
|
|
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);
|
|
2504
|
+
}
|
|
2057
2505
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2506
|
+
return aggregates;
|
|
2507
|
+
}
|
|
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
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
function wrapWithAliasFilterNode(currentNode, ast, alias, predicateTargetType, nextPlanNodeId) {
|
|
2515
|
+
const aliasPredicates = getAliasPredicates(ast, alias, predicateTargetType);
|
|
2516
|
+
if (aliasPredicates.length === 0) {
|
|
2517
|
+
return currentNode;
|
|
2060
2518
|
}
|
|
2061
|
-
return
|
|
2519
|
+
return {
|
|
2520
|
+
alias,
|
|
2521
|
+
id: nextPlanNodeId(),
|
|
2522
|
+
input: currentNode,
|
|
2523
|
+
op: "filter",
|
|
2524
|
+
predicateTargetType,
|
|
2525
|
+
predicates: aliasPredicates.map((predicate2) => predicate2.expression)
|
|
2526
|
+
};
|
|
2062
2527
|
}
|
|
2063
|
-
function
|
|
2064
|
-
|
|
2065
|
-
const
|
|
2066
|
-
if (
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
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 };
|
|
2071
2540
|
}
|
|
2072
|
-
if (
|
|
2073
|
-
|
|
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
|
+
};
|
|
2548
|
+
}
|
|
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 {
|
|
2074
2568
|
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2075
|
-
"
|
|
2076
|
-
{ component: "set-operation-emitter" }
|
|
2569
|
+
"limit_offset node requires limit or offset to be present"
|
|
2077
2570
|
);
|
|
2078
2571
|
}
|
|
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
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
|
+
};
|
|
2089
2583
|
}
|
|
2090
|
-
function
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
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
|
|
2094
2600
|
);
|
|
2095
|
-
const
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
"Standard SQL emitter received HAVING clause for a plan without aggregate nodes",
|
|
2116
|
-
{ component: "standard-emitter" }
|
|
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
|
|
2117
2621
|
);
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
"
|
|
2123
|
-
|
|
2622
|
+
currentNode = wrapWithAliasFilterNode(
|
|
2623
|
+
currentNode,
|
|
2624
|
+
ast,
|
|
2625
|
+
traversal.nodeAlias,
|
|
2626
|
+
"node",
|
|
2627
|
+
nextPlanNodeId
|
|
2124
2628
|
);
|
|
2125
2629
|
}
|
|
2126
|
-
if (
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2630
|
+
if (input.vectorPredicate !== void 0) {
|
|
2631
|
+
currentNode = {
|
|
2632
|
+
id: nextPlanNodeId(),
|
|
2633
|
+
input: currentNode,
|
|
2634
|
+
op: "vector_knn",
|
|
2635
|
+
predicate: input.vectorPredicate
|
|
2636
|
+
};
|
|
2131
2637
|
}
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2638
|
+
return appendAggregateSortLimitAndProjectNodes(
|
|
2639
|
+
currentNode,
|
|
2640
|
+
ast,
|
|
2641
|
+
nextPlanNodeId,
|
|
2642
|
+
input.effectiveLimit,
|
|
2643
|
+
input.collapsedTraversalCteAlias
|
|
2644
|
+
);
|
|
2645
|
+
}
|
|
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
|
+
);
|
|
2695
|
+
}
|
|
2696
|
+
function lowerComposableQueryToLogicalPlanNode(query, dialect, graphId, nextPlanNodeId) {
|
|
2697
|
+
if ("__type" in query) {
|
|
2698
|
+
return lowerSetOperationToLogicalPlanNode(
|
|
2699
|
+
query,
|
|
2700
|
+
graphId,
|
|
2701
|
+
dialect,
|
|
2702
|
+
nextPlanNodeId
|
|
2136
2703
|
);
|
|
2137
2704
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
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
|
+
});
|
|
2143
2714
|
}
|
|
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);
|
|
2144
2728
|
}
|
|
2145
|
-
function
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
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
|
+
};
|
|
2163
2754
|
}
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
}
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
const byAliasAndType = /* @__PURE__ */ new Map();
|
|
2175
|
-
for (const predicate2 of ast.predicates) {
|
|
2176
|
-
const key = buildPredicateIndexKey(
|
|
2177
|
-
predicate2.targetAlias,
|
|
2178
|
-
resolvePredicateTargetType(predicate2)
|
|
2179
|
-
);
|
|
2180
|
-
const existing = byAliasAndType.get(key);
|
|
2181
|
-
if (existing === void 0) {
|
|
2182
|
-
byAliasAndType.set(key, [predicate2]);
|
|
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 };
|
|
2183
2765
|
} else {
|
|
2184
|
-
|
|
2766
|
+
currentNode = { ...limitOffsetBase, limit: op.limit };
|
|
2185
2767
|
}
|
|
2186
2768
|
}
|
|
2187
|
-
return
|
|
2188
|
-
}
|
|
2189
|
-
function getPredicatesForAlias(predicateIndex, alias, targetType) {
|
|
2190
|
-
return predicateIndex.byAliasAndType.get(
|
|
2191
|
-
buildPredicateIndexKey(alias, targetType)
|
|
2192
|
-
) ?? EMPTY_PREDICATES;
|
|
2769
|
+
return currentNode;
|
|
2193
2770
|
}
|
|
2194
|
-
function
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
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
|
+
};
|
|
2198
2783
|
}
|
|
2199
|
-
function
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
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
|
+
};
|
|
2210
2796
|
}
|
|
2211
|
-
function
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
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
|
+
};
|
|
2221
2811
|
}
|
|
2222
2812
|
|
|
2223
|
-
// src/query/compiler/
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
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
|
+
};
|
|
2236
2837
|
}
|
|
2237
|
-
|
|
2238
|
-
|
|
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
|
+
};
|
|
2239
2853
|
}
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
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
|
+
};
|
|
2246
2872
|
}
|
|
2247
|
-
|
|
2248
|
-
|
|
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
|
+
};
|
|
2249
2891
|
}
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
"id",
|
|
2254
|
-
"kind",
|
|
2255
|
-
"props",
|
|
2256
|
-
"version",
|
|
2257
|
-
"valid_from",
|
|
2258
|
-
"valid_to",
|
|
2259
|
-
"created_at",
|
|
2260
|
-
"updated_at",
|
|
2261
|
-
"deleted_at"
|
|
2262
|
-
];
|
|
2263
|
-
var EDGE_COLUMNS = [
|
|
2264
|
-
"id",
|
|
2265
|
-
"kind",
|
|
2266
|
-
"from_id",
|
|
2267
|
-
"to_id",
|
|
2268
|
-
"props",
|
|
2269
|
-
"valid_from",
|
|
2270
|
-
"valid_to",
|
|
2271
|
-
"created_at",
|
|
2272
|
-
"updated_at",
|
|
2273
|
-
"deleted_at"
|
|
2274
|
-
];
|
|
2275
|
-
var EMPTY_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
2276
|
-
function quoteIdentifier(identifier) {
|
|
2277
|
-
return drizzleOrm.sql.raw(`"${identifier.replaceAll('"', '""')}"`);
|
|
2278
|
-
}
|
|
2279
|
-
function shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns) {
|
|
2280
|
-
if (alwaysRequiredColumns?.has(column)) return true;
|
|
2281
|
-
if (requiredColumns === void 0) return true;
|
|
2282
|
-
return requiredColumns.has(column);
|
|
2283
|
-
}
|
|
2284
|
-
function addRequiredColumn(requiredColumnsByAlias, alias, column) {
|
|
2285
|
-
const existing = requiredColumnsByAlias.get(alias);
|
|
2286
|
-
if (existing) {
|
|
2287
|
-
existing.add(column);
|
|
2288
|
-
return;
|
|
2289
|
-
}
|
|
2290
|
-
requiredColumnsByAlias.set(alias, /* @__PURE__ */ new Set([column]));
|
|
2892
|
+
});
|
|
2893
|
+
state = logicalPlanPass.state;
|
|
2894
|
+
return state;
|
|
2291
2895
|
}
|
|
2292
|
-
function
|
|
2293
|
-
const
|
|
2294
|
-
|
|
2295
|
-
|
|
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);
|
|
2296
2900
|
}
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
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;
|
|
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
|
+
);
|
|
2302
2917
|
}
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
if (field2.isSystemField) {
|
|
2307
|
-
addRequiredColumn(
|
|
2308
|
-
requiredColumnsByAlias,
|
|
2309
|
-
field2.alias,
|
|
2310
|
-
mapSelectiveSystemFieldToColumn(field2.field)
|
|
2918
|
+
if (logicalPlan === void 0) {
|
|
2919
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2920
|
+
"Logical plan pass did not initialize plan state"
|
|
2311
2921
|
);
|
|
2312
|
-
return;
|
|
2313
2922
|
}
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
}
|
|
2319
|
-
function isAggregateExpr(source) {
|
|
2320
|
-
return "__type" in source && source.__type === "aggregate";
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
// src/query/compiler/emitter/standard-builders.ts
|
|
2324
|
-
function compileColumnReference(tableAlias, column) {
|
|
2325
|
-
if (tableAlias === void 0) {
|
|
2326
|
-
return drizzleOrm.sql.raw(column);
|
|
2923
|
+
if (vlTraversal === void 0) {
|
|
2924
|
+
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2925
|
+
"Recursive traversal pass did not select traversal"
|
|
2926
|
+
);
|
|
2327
2927
|
}
|
|
2328
|
-
|
|
2329
|
-
}
|
|
2330
|
-
function compileNodeSelectColumns(tableAlias, alias, requiredColumns) {
|
|
2331
|
-
return NODE_COLUMNS.filter(
|
|
2332
|
-
(column) => column === "id" || column === "kind" || shouldProjectColumn(requiredColumns, column)
|
|
2333
|
-
).map(
|
|
2334
|
-
(column) => drizzleOrm.sql`${compileColumnReference(tableAlias, column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
|
|
2335
|
-
);
|
|
2336
|
-
}
|
|
2337
|
-
function compileEdgeSelectColumns(tableAlias, alias, requiredColumns) {
|
|
2338
|
-
return EDGE_COLUMNS.filter(
|
|
2339
|
-
(column) => shouldProjectColumn(requiredColumns, column)
|
|
2340
|
-
).map(
|
|
2341
|
-
(column) => drizzleOrm.sql`${compileColumnReference(tableAlias, column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
|
|
2342
|
-
);
|
|
2343
|
-
}
|
|
2344
|
-
function buildStandardStartCte(input) {
|
|
2345
|
-
const { ast, ctx, graphId, predicateIndex, requiredColumnsByAlias } = input;
|
|
2346
|
-
const alias = ast.start.alias;
|
|
2347
|
-
const kinds = ast.start.kinds;
|
|
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
|
-
`;
|
|
2372
|
-
}
|
|
2373
|
-
function buildStandardTraversalCte(input) {
|
|
2374
|
-
const {
|
|
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
|
-
|
|
2402
|
-
);
|
|
2403
|
-
const
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
getPredicatesForAlias(predicateIndex, traversal.edgeAlias, "edge"),
|
|
2409
|
-
edgeCteContext
|
|
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
|
|
3008
|
+
);
|
|
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
|
-
|
|
2446
|
-
}
|
|
2447
|
-
return drizzleOrm.sql`
|
|
2448
|
-
SELECT ${drizzleOrm.sql.join(selectColumns, drizzleOrm.sql`, `)}
|
|
2449
|
-
FROM cte_${drizzleOrm.sql.raw(previousAlias)}
|
|
2450
|
-
JOIN ${ctx.schema.edgesTable} e ON cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id = e.${drizzleOrm.sql.raw(branch.joinField)}
|
|
2451
|
-
AND cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind = e.${drizzleOrm.sql.raw(branch.joinKindField)}
|
|
2452
|
-
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
2453
|
-
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
2454
|
-
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
2455
|
-
WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
|
|
2456
|
-
`;
|
|
2457
|
-
}
|
|
2458
|
-
const directJoinField = traversal.direction === "out" ? "from_id" : "to_id";
|
|
2459
|
-
const directTargetField = traversal.direction === "out" ? "to_id" : "from_id";
|
|
2460
|
-
const directJoinKindField = traversal.direction === "out" ? "from_kind" : "to_kind";
|
|
2461
|
-
const directTargetKindField = traversal.direction === "out" ? "to_kind" : "from_kind";
|
|
2462
|
-
const directBranch = compileTraversalBranch({
|
|
2463
|
-
edgeKinds: directEdgeKinds,
|
|
2464
|
-
joinField: directJoinField,
|
|
2465
|
-
joinKindField: directJoinKindField,
|
|
2466
|
-
targetField: directTargetField,
|
|
2467
|
-
targetKindField: directTargetKindField
|
|
2468
|
-
});
|
|
2469
|
-
if (inverseEdgeKinds.length === 0) {
|
|
2470
|
-
if (traversalLimitValue !== void 0) {
|
|
2471
|
-
return drizzleOrm.sql`
|
|
2472
|
-
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2473
|
-
SELECT * FROM (
|
|
2474
|
-
${directBranch}
|
|
2475
|
-
) AS traversal_rows
|
|
2476
|
-
LIMIT ${traversalLimitValue}
|
|
2477
|
-
)
|
|
2478
|
-
`;
|
|
3050
|
+
recursiveFilterClauses.push(branch.duplicateGuard);
|
|
2479
3051
|
}
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
const inverseTargetField = traversal.direction === "out" ? "from_id" : "to_id";
|
|
2488
|
-
const inverseJoinKindField = traversal.direction === "out" ? "to_kind" : "from_kind";
|
|
2489
|
-
const inverseTargetKindField = traversal.direction === "out" ? "from_kind" : "to_kind";
|
|
2490
|
-
const overlappingKinds = inverseEdgeKinds.filter(
|
|
2491
|
-
(kind) => directEdgeKinds.includes(kind)
|
|
2492
|
-
);
|
|
2493
|
-
const duplicateGuard = overlappingKinds.length > 0 ? drizzleOrm.sql`NOT (e.from_id = e.to_id AND ${compileKindFilter(
|
|
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
|
-
`;
|
|
2516
|
-
}
|
|
2517
|
-
return drizzleOrm.sql`
|
|
2518
|
-
cte_${drizzleOrm.sql.raw(nodeAlias)} AS ${cteMaterialization}(
|
|
2519
|
-
${directBranch}
|
|
2520
|
-
UNION ALL
|
|
2521
|
-
${inverseBranch}
|
|
2522
|
-
)
|
|
2523
|
-
`;
|
|
2524
|
-
}
|
|
2525
|
-
function compileAggregateExprFromSource(expr, dialect) {
|
|
2526
|
-
const { field: field2 } = expr;
|
|
2527
|
-
const fn = expr.function;
|
|
2528
|
-
switch (fn) {
|
|
2529
|
-
case "count":
|
|
2530
|
-
case "countDistinct":
|
|
2531
|
-
case "sum":
|
|
2532
|
-
case "avg":
|
|
2533
|
-
case "min":
|
|
2534
|
-
case "max": {
|
|
2535
|
-
const cteAlias = `cte_${field2.alias}`;
|
|
2536
|
-
const column = compileFieldValue(
|
|
2537
|
-
field2,
|
|
2538
|
-
dialect,
|
|
2539
|
-
field2.valueType,
|
|
2540
|
-
cteAlias
|
|
2541
|
-
);
|
|
2542
|
-
if (fn === "countDistinct") {
|
|
2543
|
-
return drizzleOrm.sql`COUNT(DISTINCT ${column})`;
|
|
2544
|
-
}
|
|
2545
|
-
return drizzleOrm.sql`${drizzleOrm.sql.raw(fn.toUpperCase())}(${column})`;
|
|
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`);
|
|
2546
3059
|
}
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
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`
|
|
2550
3066
|
);
|
|
2551
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 `)}
|
|
3087
|
+
JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
|
|
3088
|
+
AND n.id = e.${drizzleOrm.sql.raw(branch.targetField)}
|
|
3089
|
+
AND n.kind = e.${drizzleOrm.sql.raw(branch.targetKindField)}
|
|
3090
|
+
WHERE ${drizzleOrm.sql.join(recursiveFilterClauses, drizzleOrm.sql` AND `)}
|
|
3091
|
+
`;
|
|
2552
3092
|
}
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
)
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
dialect,
|
|
2572
|
-
ast,
|
|
2573
|
-
collapsedTraversalCteAlias
|
|
2574
|
-
);
|
|
2575
|
-
}
|
|
2576
|
-
const fields = ast.projection.fields;
|
|
2577
|
-
if (fields.length === 0) {
|
|
2578
|
-
return drizzleOrm.sql.raw("*");
|
|
2579
|
-
}
|
|
2580
|
-
const projectedFields = fields.map((field2) => {
|
|
2581
|
-
const source = compileProjectedSource(field2, dialect);
|
|
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}`);
|
|
2593
|
-
}
|
|
2594
|
-
const columns = fields.map((field2) => {
|
|
2595
|
-
const cteAlias = collapsedTraversalCteAlias ?? aliasToCte.get(field2.alias) ?? `cte_${field2.alias}`;
|
|
2596
|
-
if (field2.isSystemField) {
|
|
2597
|
-
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
2598
|
-
return drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2599
|
-
}
|
|
2600
|
-
const propsColumn = `${field2.alias}_props`;
|
|
2601
|
-
const column = drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(propsColumn)}`;
|
|
2602
|
-
const pointer = chunkP5CNM325_cjs.jsonPointer([field2.field]);
|
|
2603
|
-
const extracted = compileTypedJsonExtract({
|
|
2604
|
-
column,
|
|
2605
|
-
dialect,
|
|
2606
|
-
pointer,
|
|
2607
|
-
valueType: field2.valueType
|
|
2608
|
-
});
|
|
2609
|
-
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2610
|
-
});
|
|
2611
|
-
return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
|
|
2612
|
-
}
|
|
2613
|
-
function buildStandardFromClause(input) {
|
|
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`
|
|
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({
|
|
3098
|
+
joinField: directJoinField,
|
|
3099
|
+
targetField: directTargetField,
|
|
3100
|
+
joinKindField: directJoinKindField,
|
|
3101
|
+
targetKindField: directTargetKindField,
|
|
3102
|
+
edgeKinds: directEdgeKinds
|
|
3103
|
+
});
|
|
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)
|
|
2627
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
|
+
});
|
|
3121
|
+
return drizzleOrm.sql`
|
|
3122
|
+
${directBranch}
|
|
3123
|
+
UNION ALL
|
|
3124
|
+
${inverseBranch}
|
|
3125
|
+
`;
|
|
2628
3126
|
}
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
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`);
|
|
2634
3135
|
}
|
|
2635
|
-
return
|
|
3136
|
+
return drizzleOrm.sql`
|
|
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
|
+
|
|
3143
|
+
UNION ALL
|
|
3144
|
+
|
|
3145
|
+
-- Recursive case: follow edges
|
|
3146
|
+
${recursiveBranchSql}
|
|
3147
|
+
)
|
|
3148
|
+
`;
|
|
2636
3149
|
}
|
|
2637
|
-
function
|
|
2638
|
-
|
|
2639
|
-
if (!ast.orderBy || ast.orderBy.length === 0) {
|
|
2640
|
-
return void 0;
|
|
2641
|
-
}
|
|
2642
|
-
const parts = [];
|
|
2643
|
-
for (const orderSpec of ast.orderBy) {
|
|
2644
|
-
const valueType = orderSpec.field.valueType;
|
|
2645
|
-
if (valueType === "array" || valueType === "object") {
|
|
2646
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2647
|
-
"Ordering by JSON arrays or objects is not supported"
|
|
2648
|
-
);
|
|
2649
|
-
}
|
|
2650
|
-
const cteAlias = collapsedTraversalCteAlias ?? `cte_${orderSpec.field.alias}`;
|
|
2651
|
-
const field2 = compileFieldValue(
|
|
2652
|
-
orderSpec.field,
|
|
2653
|
-
dialect,
|
|
2654
|
-
valueType,
|
|
2655
|
-
cteAlias
|
|
2656
|
-
);
|
|
2657
|
-
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
2658
|
-
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
2659
|
-
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
2660
|
-
parts.push(
|
|
2661
|
-
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
2662
|
-
drizzleOrm.sql`${field2} ${direction}`
|
|
2663
|
-
);
|
|
2664
|
-
}
|
|
2665
|
-
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
3150
|
+
function compileKindFilter2(kinds, columnExpr) {
|
|
3151
|
+
return compileKindFilter(drizzleOrm.sql.raw(columnExpr), kinds);
|
|
2666
3152
|
}
|
|
2667
|
-
function
|
|
2668
|
-
|
|
2669
|
-
return `${field2.alias}:${field2.path.join(".")}:${pointer}`;
|
|
3153
|
+
function compileNodePredicates(ast, alias, ctx) {
|
|
3154
|
+
return ast.predicates.filter((p) => p.targetAlias === alias && p.targetType !== "edge").map((p) => compilePredicateExpression(p.expression, ctx));
|
|
2670
3155
|
}
|
|
2671
|
-
function
|
|
2672
|
-
|
|
2673
|
-
|
|
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) {
|
|
2674
3162
|
return void 0;
|
|
2675
3163
|
}
|
|
2676
|
-
const
|
|
2677
|
-
const
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
allFields.push(projectedField.source);
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
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");
|
|
2686
3171
|
}
|
|
2687
|
-
for (const field2 of
|
|
2688
|
-
|
|
2689
|
-
if (!seenKeys.has(key)) {
|
|
2690
|
-
seenKeys.add(key);
|
|
2691
|
-
allFields.push(field2);
|
|
2692
|
-
}
|
|
3172
|
+
for (const field2 of selectiveFields) {
|
|
3173
|
+
markSelectiveFieldAsRequired(requiredColumnsByAlias, field2);
|
|
2693
3174
|
}
|
|
2694
|
-
if (
|
|
2695
|
-
|
|
3175
|
+
if (ast.orderBy) {
|
|
3176
|
+
for (const orderSpec of ast.orderBy) {
|
|
3177
|
+
markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
|
|
3178
|
+
}
|
|
2696
3179
|
}
|
|
2697
|
-
|
|
2698
|
-
|
|
3180
|
+
return requiredColumnsByAlias;
|
|
3181
|
+
}
|
|
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}`)}`
|
|
2699
3187
|
);
|
|
2700
|
-
return drizzleOrm.sql`GROUP BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
2701
3188
|
}
|
|
2702
|
-
function
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
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
|
+
});
|
|
2709
3196
|
}
|
|
2710
|
-
function
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
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)
|
|
3197
|
+
function compileRecursiveProjection(ast, traversal, dialect) {
|
|
3198
|
+
if (ast.selectiveFields && ast.selectiveFields.length > 0) {
|
|
3199
|
+
return compileRecursiveSelectiveProjection(
|
|
3200
|
+
ast.selectiveFields,
|
|
3201
|
+
ast,
|
|
3202
|
+
traversal,
|
|
3203
|
+
dialect
|
|
2727
3204
|
);
|
|
2728
3205
|
}
|
|
2729
|
-
const
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
)
|
|
2740
|
-
|
|
2741
|
-
}
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
}
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
}
|
|
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)}`);
|
|
3233
|
+
}
|
|
3234
|
+
if (vl.pathAlias !== void 0) {
|
|
3235
|
+
fields.push(drizzleOrm.sql`path AS ${quoteIdentifier(vl.pathAlias)}`);
|
|
2751
3236
|
}
|
|
3237
|
+
return drizzleOrm.sql.join(fields, drizzleOrm.sql`, `);
|
|
2752
3238
|
}
|
|
2753
|
-
function
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
return drizzleOrm.sql`${distanceExpr} <= ${minScore}`;
|
|
3239
|
+
function compileRecursiveSelectiveProjection(fields, ast, traversal, dialect) {
|
|
3240
|
+
const allowedAliases = /* @__PURE__ */ new Set([ast.start.alias, traversal.nodeAlias]);
|
|
3241
|
+
const columns = fields.map((field2) => {
|
|
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
|
+
);
|
|
2761
3246
|
}
|
|
2762
|
-
|
|
2763
|
-
const
|
|
2764
|
-
return drizzleOrm.sql`${
|
|
3247
|
+
if (field2.isSystemField) {
|
|
3248
|
+
const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
|
|
3249
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier(field2.outputName)}`;
|
|
2765
3250
|
}
|
|
3251
|
+
const column = drizzleOrm.sql.raw(`${field2.alias}_props`);
|
|
3252
|
+
const extracted = compileTypedJsonExtract({
|
|
3253
|
+
column,
|
|
3254
|
+
dialect,
|
|
3255
|
+
pointer: chunkP5CNM325_cjs.jsonPointer([field2.field]),
|
|
3256
|
+
valueType: field2.valueType
|
|
3257
|
+
});
|
|
3258
|
+
return drizzleOrm.sql`${extracted} AS ${quoteIdentifier(field2.outputName)}`;
|
|
3259
|
+
});
|
|
3260
|
+
const vl = traversal.variableLength;
|
|
3261
|
+
if (vl.depthAlias !== void 0) {
|
|
3262
|
+
columns.push(drizzleOrm.sql`depth AS ${quoteIdentifier(vl.depthAlias)}`);
|
|
2766
3263
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
const { ast, dialect } = input;
|
|
2770
|
-
const distanceOrder = drizzleOrm.sql`cte_embeddings.distance ASC`;
|
|
2771
|
-
const additionalOrders = [];
|
|
2772
|
-
if (ast.orderBy && ast.orderBy.length > 0) {
|
|
2773
|
-
for (const orderSpec of ast.orderBy) {
|
|
2774
|
-
const valueType = orderSpec.field.valueType;
|
|
2775
|
-
if (valueType === "array" || valueType === "object") {
|
|
2776
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
2777
|
-
"Ordering by JSON arrays or objects is not supported"
|
|
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
|
-
}
|
|
3264
|
+
if (vl.pathAlias !== void 0) {
|
|
3265
|
+
columns.push(drizzleOrm.sql`path AS ${quoteIdentifier(vl.pathAlias)}`);
|
|
2795
3266
|
}
|
|
2796
|
-
|
|
2797
|
-
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(allOrders, drizzleOrm.sql`, `)}`;
|
|
3267
|
+
return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
|
|
2798
3268
|
}
|
|
2799
|
-
function
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
if (limit !== void 0) {
|
|
2803
|
-
parts.push(drizzleOrm.sql`LIMIT ${limit}`);
|
|
2804
|
-
}
|
|
2805
|
-
if (offset !== void 0) {
|
|
2806
|
-
parts.push(drizzleOrm.sql`OFFSET ${offset}`);
|
|
3269
|
+
function compileRecursiveOrderBy(ast, dialect) {
|
|
3270
|
+
if (!ast.orderBy || ast.orderBy.length === 0) {
|
|
3271
|
+
return void 0;
|
|
2807
3272
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
var NO_ALWAYS_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
2815
|
-
function runRecursiveQueryPassPipeline(ast, graphId, ctx) {
|
|
2816
|
-
let state = {
|
|
2817
|
-
ast,
|
|
2818
|
-
ctx,
|
|
2819
|
-
graphId,
|
|
2820
|
-
logicalPlan: void 0,
|
|
2821
|
-
requiredColumnsByAlias: void 0,
|
|
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
|
-
};
|
|
2835
|
-
}
|
|
2836
|
-
});
|
|
2837
|
-
state = recursiveTraversalPass.state;
|
|
2838
|
-
const temporalPass = runCompilerPass(state, {
|
|
2839
|
-
name: "temporal_filters",
|
|
2840
|
-
execute(currentState) {
|
|
2841
|
-
return createTemporalFilterPass(
|
|
2842
|
-
currentState.ast,
|
|
2843
|
-
currentState.ctx.dialect.currentTimestamp()
|
|
3273
|
+
const parts = [];
|
|
3274
|
+
for (const orderSpec of ast.orderBy) {
|
|
3275
|
+
const valueType = orderSpec.field.valueType;
|
|
3276
|
+
if (valueType === "array" || valueType === "object") {
|
|
3277
|
+
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
3278
|
+
"Ordering by JSON arrays or objects is not supported"
|
|
2844
3279
|
);
|
|
2845
|
-
},
|
|
2846
|
-
update(currentState, temporalFilterPass) {
|
|
2847
|
-
return {
|
|
2848
|
-
...currentState,
|
|
2849
|
-
temporalFilterPass
|
|
2850
|
-
};
|
|
2851
3280
|
}
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2860
|
-
"Recursive traversal pass did not select traversal"
|
|
2861
|
-
);
|
|
2862
|
-
}
|
|
2863
|
-
return collectRequiredColumnsByAlias(currentState.ast, traversal);
|
|
2864
|
-
},
|
|
2865
|
-
update(currentState, requiredColumnsByAlias) {
|
|
2866
|
-
return {
|
|
2867
|
-
...currentState,
|
|
2868
|
-
requiredColumnsByAlias
|
|
2869
|
-
};
|
|
2870
|
-
}
|
|
2871
|
-
});
|
|
2872
|
-
state = columnPruningPass.state;
|
|
2873
|
-
const logicalPlanPass = runCompilerPass(state, {
|
|
2874
|
-
name: "logical_plan",
|
|
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
|
-
};
|
|
2889
|
-
}
|
|
2890
|
-
});
|
|
2891
|
-
state = logicalPlanPass.state;
|
|
2892
|
-
return state;
|
|
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);
|
|
2898
|
-
}
|
|
2899
|
-
var RECURSIVE_QUERY_STRATEGY_HANDLERS = {
|
|
2900
|
-
recursive_cte: compileVariableLengthQueryWithRecursiveCteStrategy
|
|
2901
|
-
};
|
|
2902
|
-
function compileVariableLengthQueryWithRecursiveCteStrategy(ast, graphId, ctx) {
|
|
2903
|
-
const passState = runRecursiveQueryPassPipeline(ast, graphId, ctx);
|
|
2904
|
-
const { dialect } = ctx;
|
|
2905
|
-
const {
|
|
2906
|
-
logicalPlan,
|
|
2907
|
-
requiredColumnsByAlias,
|
|
2908
|
-
temporalFilterPass,
|
|
2909
|
-
traversal: vlTraversal
|
|
2910
|
-
} = passState;
|
|
2911
|
-
if (temporalFilterPass === void 0) {
|
|
2912
|
-
throw new chunk44SXEVF4_cjs.CompilerInvariantError(
|
|
2913
|
-
"Temporal filter pass did not initialize temporal state"
|
|
3281
|
+
const field2 = compileFieldValue(orderSpec.field, dialect, valueType);
|
|
3282
|
+
const direction = drizzleOrm.sql.raw(orderSpec.direction.toUpperCase());
|
|
3283
|
+
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
3284
|
+
const nullsDirection = drizzleOrm.sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
3285
|
+
parts.push(
|
|
3286
|
+
drizzleOrm.sql`(${field2} IS NULL) ${nullsDirection}`,
|
|
3287
|
+
drizzleOrm.sql`${field2} ${direction}`
|
|
2914
3288
|
);
|
|
2915
3289
|
}
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
3290
|
+
return drizzleOrm.sql`ORDER BY ${drizzleOrm.sql.join(parts, drizzleOrm.sql`, `)}`;
|
|
3291
|
+
}
|
|
3292
|
+
function compileLimitOffset(ast) {
|
|
3293
|
+
const parts = [];
|
|
3294
|
+
if (ast.limit !== void 0) {
|
|
3295
|
+
parts.push(drizzleOrm.sql`LIMIT ${ast.limit}`);
|
|
2920
3296
|
}
|
|
2921
|
-
if (
|
|
2922
|
-
|
|
2923
|
-
"Recursive traversal pass did not select traversal"
|
|
2924
|
-
);
|
|
3297
|
+
if (ast.offset !== void 0) {
|
|
3298
|
+
parts.push(drizzleOrm.sql`OFFSET ${ast.offset}`);
|
|
2925
3299
|
}
|
|
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
|
-
});
|
|
2947
|
-
}
|
|
2948
|
-
function hasVariableLengthTraversal(ast) {
|
|
2949
|
-
return ast.traversals.some((t) => t.variableLength !== void 0);
|
|
3300
|
+
return parts.length > 0 ? drizzleOrm.sql.join(parts, drizzleOrm.sql` `) : void 0;
|
|
2950
3301
|
}
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
const direction = traversal.direction;
|
|
2962
|
-
const vl = traversal.variableLength;
|
|
2963
|
-
const shouldEnforceCycleCheck = vl.cyclePolicy !== "allow";
|
|
2964
|
-
const shouldTrackPath = shouldEnforceCycleCheck || vl.pathAlias !== void 0;
|
|
2965
|
-
const recursiveJoinRequiredColumns = /* @__PURE__ */ new Set(["id"]);
|
|
2966
|
-
if (previousNodeKinds.length > 1) {
|
|
2967
|
-
recursiveJoinRequiredColumns.add("kind");
|
|
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`);
|
|
2968
3312
|
}
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
"n0",
|
|
2973
|
-
startAlias,
|
|
2974
|
-
requiredStartColumns,
|
|
2975
|
-
NO_ALWAYS_REQUIRED_COLUMNS
|
|
2976
|
-
);
|
|
2977
|
-
const startColumnsFromRecursive = compileNodeSelectColumnsFromRecursiveRow(
|
|
2978
|
-
startAlias,
|
|
2979
|
-
requiredStartColumns,
|
|
2980
|
-
NO_ALWAYS_REQUIRED_COLUMNS
|
|
2981
|
-
);
|
|
2982
|
-
const nodeColumnsFromBase = compileNodeSelectColumnsFromTable(
|
|
2983
|
-
"n0",
|
|
2984
|
-
nodeAlias,
|
|
2985
|
-
requiredNodeColumns,
|
|
2986
|
-
recursiveJoinRequiredColumns
|
|
2987
|
-
);
|
|
2988
|
-
const nodeColumnsFromRecursive = compileNodeSelectColumnsFromTable(
|
|
2989
|
-
"n",
|
|
2990
|
-
nodeAlias,
|
|
2991
|
-
requiredNodeColumns,
|
|
2992
|
-
recursiveJoinRequiredColumns
|
|
2993
|
-
);
|
|
2994
|
-
const startKindFilter = compileKindFilter2(startKinds, "n0.kind");
|
|
2995
|
-
const nodeKindFilter = compileKindFilter2(nodeKinds, "n.kind");
|
|
2996
|
-
const startTemporalFilter = temporalFilterPass.forAlias("n0");
|
|
2997
|
-
const edgeTemporalFilter = temporalFilterPass.forAlias("e");
|
|
2998
|
-
const nodeTemporalFilter = temporalFilterPass.forAlias("n");
|
|
2999
|
-
const startContext = { ...ctx, cteColumnPrefix: "" };
|
|
3000
|
-
const startPredicates = compileNodePredicates(ast, startAlias, startContext);
|
|
3001
|
-
const edgeContext = { ...ctx, cteColumnPrefix: "e" };
|
|
3002
|
-
const edgePredicates = compileEdgePredicates(
|
|
3003
|
-
ast,
|
|
3004
|
-
traversal.edgeAlias,
|
|
3005
|
-
edgeContext
|
|
3006
|
-
);
|
|
3007
|
-
const targetContext = { ...ctx, cteColumnPrefix: "n" };
|
|
3008
|
-
const targetNodePredicates = compileNodePredicates(
|
|
3009
|
-
ast,
|
|
3010
|
-
nodeAlias,
|
|
3011
|
-
targetContext
|
|
3012
|
-
);
|
|
3013
|
-
if (vl.maxDepth > MAX_EXPLICIT_RECURSIVE_DEPTH) {
|
|
3014
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
3015
|
-
`Recursive traversal maxHops(${vl.maxDepth}) exceeds maximum explicit depth of ${MAX_EXPLICIT_RECURSIVE_DEPTH}`
|
|
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`
|
|
3016
3316
|
);
|
|
3017
3317
|
}
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
const pathExtension = shouldTrackPath ? dialect.extendPath(drizzleOrm.sql.raw("r.path"), drizzleOrm.sql.raw("n.id")) : void 0;
|
|
3023
|
-
const baseWhereClauses = [
|
|
3024
|
-
drizzleOrm.sql`n0.graph_id = ${graphId}`,
|
|
3025
|
-
startKindFilter,
|
|
3026
|
-
startTemporalFilter,
|
|
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);
|
|
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
|
+
);
|
|
3038
3322
|
}
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3323
|
+
}
|
|
3324
|
+
function quoteIdentifier2(name) {
|
|
3325
|
+
return `"${name.replaceAll('"', '""')}"`;
|
|
3326
|
+
}
|
|
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
|
+
};
|
|
3338
|
+
}
|
|
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;
|
|
3350
|
+
}
|
|
3351
|
+
return decodeByValueType(normalized, typeInfo.valueType);
|
|
3352
|
+
}
|
|
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);
|
|
3049
3365
|
}
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
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;
|
|
3057
3373
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
);
|
|
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;
|
|
3385
|
+
}
|
|
3065
3386
|
}
|
|
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
|
-
`;
|
|
3387
|
+
case "string":
|
|
3388
|
+
case "date":
|
|
3389
|
+
case "unknown": {
|
|
3390
|
+
return value;
|
|
3391
|
+
}
|
|
3392
|
+
default: {
|
|
3393
|
+
return value;
|
|
3080
3394
|
}
|
|
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
3395
|
}
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3396
|
+
}
|
|
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
|
+
}
|
|
3109
3427
|
);
|
|
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
3428
|
}
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
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
|
+
}
|
|
3436
|
+
);
|
|
3133
3437
|
}
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
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
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
return filtered;
|
|
3447
|
+
}
|
|
3142
3448
|
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
`;
|
|
3449
|
+
// src/store/row-mappers.ts
|
|
3450
|
+
function nullToUndefined2(value) {
|
|
3451
|
+
return value === null ? void 0 : value;
|
|
3147
3452
|
}
|
|
3148
|
-
function
|
|
3149
|
-
|
|
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
|
+
};
|
|
3150
3462
|
}
|
|
3151
|
-
function
|
|
3152
|
-
return
|
|
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
|
+
};
|
|
3153
3472
|
}
|
|
3154
|
-
function
|
|
3155
|
-
|
|
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
|
+
};
|
|
3156
3486
|
}
|
|
3157
|
-
function
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
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: [] };
|
|
3169
3538
|
}
|
|
3170
|
-
|
|
3171
|
-
|
|
3539
|
+
const maxDepth = Math.min(
|
|
3540
|
+
options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
|
|
3541
|
+
MAX_RECURSIVE_DEPTH
|
|
3542
|
+
);
|
|
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"
|
|
3562
|
+
);
|
|
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)
|
|
3577
|
+
);
|
|
3578
|
+
const edges = edgeRows.map(
|
|
3579
|
+
(row) => mapSubgraphEdgeRow(row, edgeProjectionPlan)
|
|
3580
|
+
);
|
|
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
|
+
])
|
|
3595
|
+
);
|
|
3596
|
+
const edgeKinds = new Map(
|
|
3597
|
+
Object.entries(graph.edges).map(([kind, definition]) => [
|
|
3598
|
+
kind,
|
|
3599
|
+
{ schema: definition.type.schema }
|
|
3600
|
+
])
|
|
3601
|
+
);
|
|
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)
|
|
3618
|
+
);
|
|
3172
3619
|
}
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
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;
|
|
3629
|
+
}
|
|
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
|
+
});
|
|
3176
3637
|
}
|
|
3177
3638
|
}
|
|
3178
|
-
return
|
|
3639
|
+
return {
|
|
3640
|
+
includeMeta,
|
|
3641
|
+
propertyFields: [...propertyFields.values()]
|
|
3642
|
+
};
|
|
3179
3643
|
}
|
|
3180
|
-
function
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
);
|
|
3644
|
+
function getIncludedNodeKinds(graph, includeKinds) {
|
|
3645
|
+
if (includeKinds === void 0 || includeKinds.length === 0) {
|
|
3646
|
+
return Object.keys(graph.nodes);
|
|
3647
|
+
}
|
|
3648
|
+
return dedupeStrings(includeKinds);
|
|
3186
3649
|
}
|
|
3187
|
-
function
|
|
3188
|
-
return
|
|
3189
|
-
(column) => shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
|
|
3190
|
-
).map((column) => {
|
|
3191
|
-
const projected = `${alias}_${column}`;
|
|
3192
|
-
return drizzleOrm.sql`r.${drizzleOrm.sql.raw(projected)} AS ${drizzleOrm.sql.raw(projected)}`;
|
|
3193
|
-
});
|
|
3650
|
+
function dedupeStrings(values) {
|
|
3651
|
+
return [...new Set(values)];
|
|
3194
3652
|
}
|
|
3195
|
-
function
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
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`);
|
|
3203
3662
|
}
|
|
3204
|
-
const
|
|
3205
|
-
const
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
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`
|
|
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`
|
|
3228
3668
|
];
|
|
3229
|
-
if (
|
|
3230
|
-
|
|
3669
|
+
if (pathExtension !== void 0) {
|
|
3670
|
+
recursiveColumns.push(drizzleOrm.sql`${pathExtension} AS path`);
|
|
3671
|
+
}
|
|
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));
|
|
3231
3730
|
}
|
|
3232
|
-
if (
|
|
3233
|
-
|
|
3731
|
+
if (ctx.excludeRoot) {
|
|
3732
|
+
filters.push(drizzleOrm.sql`id != ${ctx.rootId}`);
|
|
3234
3733
|
}
|
|
3235
|
-
|
|
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})`;
|
|
3236
3736
|
}
|
|
3237
|
-
function
|
|
3238
|
-
const
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
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);
|
|
3754
|
+
}
|
|
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);
|
|
3776
|
+
}
|
|
3777
|
+
function buildMetadataColumns(alias, plan, columns) {
|
|
3778
|
+
if (plan.projectedKinds.size === 0) {
|
|
3779
|
+
return columns.map((col) => drizzleOrm.sql`${drizzleOrm.sql.raw(`${alias}.${col}`)}`);
|
|
3261
3780
|
}
|
|
3262
|
-
|
|
3263
|
-
|
|
3781
|
+
const metaKinds = [...plan.fullKinds];
|
|
3782
|
+
for (const [kind, kindPlan] of plan.projectedKinds) {
|
|
3783
|
+
if (kindPlan.includeMeta) metaKinds.push(kind);
|
|
3264
3784
|
}
|
|
3265
|
-
|
|
3266
|
-
}
|
|
3267
|
-
function compileRecursiveOrderBy(ast, dialect) {
|
|
3268
|
-
if (!ast.orderBy || ast.orderBy.length === 0) {
|
|
3269
|
-
return void 0;
|
|
3785
|
+
if (metaKinds.length === 0) {
|
|
3786
|
+
return columns.map((col) => drizzleOrm.sql`NULL AS ${drizzleOrm.sql.raw(col)}`);
|
|
3270
3787
|
}
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
const valueType = orderSpec.field.valueType;
|
|
3274
|
-
if (valueType === "array" || valueType === "object") {
|
|
3275
|
-
throw new chunk44SXEVF4_cjs.UnsupportedPredicateError(
|
|
3276
|
-
"Ordering by JSON arrays or objects is not supported"
|
|
3277
|
-
);
|
|
3278
|
-
}
|
|
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
|
-
);
|
|
3788
|
+
if (metaKinds.length === plan.fullKinds.length + plan.projectedKinds.size) {
|
|
3789
|
+
return columns.map((col) => drizzleOrm.sql`${drizzleOrm.sql.raw(`${alias}.${col}`)}`);
|
|
3287
3790
|
}
|
|
3288
|
-
|
|
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
|
+
);
|
|
3289
3795
|
}
|
|
3290
|
-
function
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
parts.push(drizzleOrm.sql`LIMIT ${ast.limit}`);
|
|
3796
|
+
function buildFullPropsColumn(alias, plan) {
|
|
3797
|
+
if (plan.projectedKinds.size === 0) {
|
|
3798
|
+
return drizzleOrm.sql`${drizzleOrm.sql.raw(`${alias}.props`)} AS props`;
|
|
3294
3799
|
}
|
|
3295
|
-
if (
|
|
3296
|
-
|
|
3800
|
+
if (plan.fullKinds.length === 0) {
|
|
3801
|
+
return drizzleOrm.sql`NULL AS props`;
|
|
3297
3802
|
}
|
|
3298
|
-
|
|
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`;
|
|
3299
3805
|
}
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
);
|
|
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)}`
|
|
3818
|
+
);
|
|
3819
|
+
}
|
|
3315
3820
|
}
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3821
|
+
return columns;
|
|
3822
|
+
}
|
|
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
|
|
3319
3828
|
);
|
|
3320
3829
|
}
|
|
3321
3830
|
}
|
|
3322
|
-
function
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
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
|
+
});
|
|
3838
|
+
}
|
|
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
|
+
});
|
|
3856
|
+
}
|
|
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
|
}
|
|
@@ -6367,24 +6843,102 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6367
6843
|
if (optimizedResult !== void 0) {
|
|
6368
6844
|
return optimizedResult;
|
|
6369
6845
|
}
|
|
6370
|
-
const compiled = this.compile();
|
|
6371
|
-
const rawRows = await this.#config.backend.execute(compiled);
|
|
6372
|
-
this.#config.dialect ?? "sqlite";
|
|
6373
|
-
const rows = transformPathColumns(rawRows, this.#state);
|
|
6374
|
-
return mapResults(
|
|
6375
|
-
rows,
|
|
6376
|
-
this.#state.startAlias,
|
|
6377
|
-
this.#state.traversals,
|
|
6378
|
-
this.#selectFn
|
|
6379
|
-
);
|
|
6846
|
+
const compiled = this.compile();
|
|
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);
|
|
6876
|
+
this.#config.dialect ?? "sqlite";
|
|
6877
|
+
const rows = transformPathColumns(rawRows, this.#state);
|
|
6878
|
+
return mapResults(
|
|
6879
|
+
rows,
|
|
6880
|
+
this.#state.startAlias,
|
|
6881
|
+
this.#state.traversals,
|
|
6882
|
+
this.#selectFn
|
|
6883
|
+
);
|
|
6884
|
+
}
|
|
6885
|
+
/**
|
|
6886
|
+
* Attempts optimized execution by tracking which fields the select callback accesses.
|
|
6887
|
+
*
|
|
6888
|
+
* Returns undefined if optimization is not possible (callback uses method calls,
|
|
6889
|
+
* computations, or returns whole nodes).
|
|
6890
|
+
*/
|
|
6891
|
+
async #tryOptimizedExecution() {
|
|
6892
|
+
const selectiveFields = this.#getSelectiveFieldsForExecute();
|
|
6893
|
+
if (selectiveFields === void 0) {
|
|
6894
|
+
return void 0;
|
|
6895
|
+
}
|
|
6896
|
+
let compiled;
|
|
6897
|
+
if (this.#cachedOptimizedCompiled === NOT_COMPUTED) {
|
|
6898
|
+
const baseAst = buildQueryAst(this.#config, this.#state);
|
|
6899
|
+
const selectiveAst = {
|
|
6900
|
+
...baseAst,
|
|
6901
|
+
selectiveFields
|
|
6902
|
+
};
|
|
6903
|
+
compiled = compileQuery(
|
|
6904
|
+
selectiveAst,
|
|
6905
|
+
this.#config.graphId,
|
|
6906
|
+
this.#compileOptions()
|
|
6907
|
+
);
|
|
6908
|
+
this.#cachedOptimizedCompiled = compiled;
|
|
6909
|
+
} else {
|
|
6910
|
+
compiled = this.#cachedOptimizedCompiled;
|
|
6911
|
+
}
|
|
6912
|
+
const rawSelectiveRows = await this.#requireBackend().execute(compiled);
|
|
6913
|
+
this.#config.dialect ?? "sqlite";
|
|
6914
|
+
const rows = transformPathColumns(rawSelectiveRows, this.#state);
|
|
6915
|
+
try {
|
|
6916
|
+
return mapSelectiveResults(
|
|
6917
|
+
rows,
|
|
6918
|
+
this.#state,
|
|
6919
|
+
selectiveFields,
|
|
6920
|
+
this.#config.schemaIntrospector,
|
|
6921
|
+
this.#selectFn
|
|
6922
|
+
);
|
|
6923
|
+
} catch (error) {
|
|
6924
|
+
if (error instanceof MissingSelectiveFieldError) {
|
|
6925
|
+
this.#cachedSelectiveFieldsForExecute = void 0;
|
|
6926
|
+
this.#cachedOptimizedCompiled = NOT_COMPUTED;
|
|
6927
|
+
return void 0;
|
|
6928
|
+
}
|
|
6929
|
+
if (error instanceof chunk44SXEVF4_cjs.UnsupportedPredicateError) {
|
|
6930
|
+
this.#cachedSelectiveFieldsForExecute = void 0;
|
|
6931
|
+
this.#cachedOptimizedCompiled = NOT_COMPUTED;
|
|
6932
|
+
return void 0;
|
|
6933
|
+
}
|
|
6934
|
+
throw error;
|
|
6935
|
+
}
|
|
6380
6936
|
}
|
|
6381
6937
|
/**
|
|
6382
|
-
* Attempts optimized execution
|
|
6383
|
-
*
|
|
6384
|
-
* Returns undefined if optimization is not possible (callback uses method calls,
|
|
6385
|
-
* computations, or returns whole nodes).
|
|
6938
|
+
* Attempts optimized execution against a provided backend.
|
|
6939
|
+
* Mirror of #tryOptimizedExecution but delegates to the given backend.
|
|
6386
6940
|
*/
|
|
6387
|
-
async #
|
|
6941
|
+
async #tryOptimizedExecutionOn(backend) {
|
|
6388
6942
|
const selectiveFields = this.#getSelectiveFieldsForExecute();
|
|
6389
6943
|
if (selectiveFields === void 0) {
|
|
6390
6944
|
return void 0;
|
|
@@ -6405,7 +6959,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6405
6959
|
} else {
|
|
6406
6960
|
compiled = this.#cachedOptimizedCompiled;
|
|
6407
6961
|
}
|
|
6408
|
-
const rawSelectiveRows = await
|
|
6962
|
+
const rawSelectiveRows = await backend.execute(compiled);
|
|
6409
6963
|
this.#config.dialect ?? "sqlite";
|
|
6410
6964
|
const rows = transformPathColumns(rawSelectiveRows, this.#state);
|
|
6411
6965
|
try {
|
|
@@ -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
|
|
@@ -8340,6 +8917,35 @@ function createEdgeCollection(config) {
|
|
|
8340
8917
|
executeHardDelete: executeEdgeHardDelete2,
|
|
8341
8918
|
matchesTemporalMode
|
|
8342
8919
|
} = config;
|
|
8920
|
+
const mapRows = (rows) => rows.map((row) => narrowEdge(rowToEdge2(row)));
|
|
8921
|
+
async function findEdgesFrom(from, target) {
|
|
8922
|
+
const rows = await target.findEdgesByKind({
|
|
8923
|
+
graphId,
|
|
8924
|
+
kind,
|
|
8925
|
+
fromKind: from.kind,
|
|
8926
|
+
fromId: from.id,
|
|
8927
|
+
excludeDeleted: true
|
|
8928
|
+
});
|
|
8929
|
+
return mapRows(rows);
|
|
8930
|
+
}
|
|
8931
|
+
async function findEdgesTo(to, target) {
|
|
8932
|
+
const rows = await target.findEdgesByKind({
|
|
8933
|
+
graphId,
|
|
8934
|
+
kind,
|
|
8935
|
+
toKind: to.kind,
|
|
8936
|
+
toId: to.id,
|
|
8937
|
+
excludeDeleted: true
|
|
8938
|
+
});
|
|
8939
|
+
return mapRows(rows);
|
|
8940
|
+
}
|
|
8941
|
+
function buildFindByEndpointsOptions(options) {
|
|
8942
|
+
const result = {};
|
|
8943
|
+
if (options?.matchOn !== void 0)
|
|
8944
|
+
result.matchOn = options.matchOn;
|
|
8945
|
+
if (options?.props !== void 0)
|
|
8946
|
+
result.props = options.props;
|
|
8947
|
+
return result;
|
|
8948
|
+
}
|
|
8343
8949
|
return {
|
|
8344
8950
|
async create(from, to, props, options) {
|
|
8345
8951
|
const result = await executeEdgeCreate2(
|
|
@@ -8395,24 +9001,32 @@ function createEdgeCollection(config) {
|
|
|
8395
9001
|
return narrowEdge(result);
|
|
8396
9002
|
},
|
|
8397
9003
|
async findFrom(from) {
|
|
8398
|
-
|
|
8399
|
-
graphId,
|
|
8400
|
-
kind,
|
|
8401
|
-
fromKind: from.kind,
|
|
8402
|
-
fromId: from.id,
|
|
8403
|
-
excludeDeleted: true
|
|
8404
|
-
});
|
|
8405
|
-
return rows.map((row) => narrowEdge(rowToEdge2(row)));
|
|
9004
|
+
return findEdgesFrom(from, backend);
|
|
8406
9005
|
},
|
|
8407
9006
|
async findTo(to) {
|
|
8408
|
-
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
}
|
|
8415
|
-
|
|
9007
|
+
return findEdgesTo(to, backend);
|
|
9008
|
+
},
|
|
9009
|
+
batchFindFrom(from) {
|
|
9010
|
+
return { executeOn: (target) => findEdgesFrom(from, target) };
|
|
9011
|
+
},
|
|
9012
|
+
batchFindTo(to) {
|
|
9013
|
+
return { executeOn: (target) => findEdgesTo(to, target) };
|
|
9014
|
+
},
|
|
9015
|
+
batchFindByEndpoints(from, to, options) {
|
|
9016
|
+
return {
|
|
9017
|
+
executeOn: async (target) => {
|
|
9018
|
+
const result = await config.executeFindByEndpoints(
|
|
9019
|
+
kind,
|
|
9020
|
+
from.kind,
|
|
9021
|
+
from.id,
|
|
9022
|
+
to.kind,
|
|
9023
|
+
to.id,
|
|
9024
|
+
target,
|
|
9025
|
+
buildFindByEndpointsOptions(options)
|
|
9026
|
+
);
|
|
9027
|
+
return result === void 0 ? [] : [narrowEdge(result)];
|
|
9028
|
+
}
|
|
9029
|
+
};
|
|
8416
9030
|
},
|
|
8417
9031
|
async delete(id) {
|
|
8418
9032
|
await executeEdgeDelete2(id, backend);
|
|
@@ -8446,7 +9060,7 @@ function createEdgeCollection(config) {
|
|
|
8446
9060
|
if (options?.limit !== void 0) params.limit = options.limit;
|
|
8447
9061
|
if (options?.offset !== void 0) params.offset = options.offset;
|
|
8448
9062
|
const rows = await backend.findEdgesByKind(params);
|
|
8449
|
-
return rows
|
|
9063
|
+
return mapRows(rows);
|
|
8450
9064
|
},
|
|
8451
9065
|
async count(options) {
|
|
8452
9066
|
const mode = options?.temporalMode ?? defaultTemporalMode;
|
|
@@ -8575,11 +9189,6 @@ function createEdgeCollection(config) {
|
|
|
8575
9189
|
await deleteAll(backend);
|
|
8576
9190
|
},
|
|
8577
9191
|
async findByEndpoints(from, to, options) {
|
|
8578
|
-
const findOptions = {};
|
|
8579
|
-
if (options?.matchOn !== void 0)
|
|
8580
|
-
findOptions.matchOn = options.matchOn;
|
|
8581
|
-
if (options?.props !== void 0)
|
|
8582
|
-
findOptions.props = options.props;
|
|
8583
9192
|
const result = await config.executeFindByEndpoints(
|
|
8584
9193
|
kind,
|
|
8585
9194
|
from.kind,
|
|
@@ -8587,7 +9196,7 @@ function createEdgeCollection(config) {
|
|
|
8587
9196
|
to.kind,
|
|
8588
9197
|
to.id,
|
|
8589
9198
|
backend,
|
|
8590
|
-
|
|
9199
|
+
buildFindByEndpointsOptions(options)
|
|
8591
9200
|
);
|
|
8592
9201
|
return result === void 0 ? void 0 : narrowEdge(result);
|
|
8593
9202
|
},
|
|
@@ -9283,67 +9892,6 @@ async function checkCardinalityConstraint(ctx, edgeKind, cardinality, fromKind,
|
|
|
9283
9892
|
}
|
|
9284
9893
|
}
|
|
9285
9894
|
|
|
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
9895
|
// src/store/operations/edge-operations.ts
|
|
9348
9896
|
function getEdgeRegistration(graph, kind) {
|
|
9349
9897
|
const registration = graph.edges[kind];
|
|
@@ -11217,142 +11765,6 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11217
11765
|
}
|
|
11218
11766
|
return results;
|
|
11219
11767
|
}
|
|
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
11768
|
|
|
11357
11769
|
// src/store/store.ts
|
|
11358
11770
|
var Store = class {
|
|
@@ -11556,6 +11968,46 @@ var Store = class {
|
|
|
11556
11968
|
query() {
|
|
11557
11969
|
return this.#createQueryForBackend(this.#backend);
|
|
11558
11970
|
}
|
|
11971
|
+
// === Batch Query Execution ===
|
|
11972
|
+
/**
|
|
11973
|
+
* Executes multiple queries over a single connection with snapshot consistency.
|
|
11974
|
+
*
|
|
11975
|
+
* Acquires one connection via an implicit transaction, executes each query
|
|
11976
|
+
* sequentially on that connection, and returns a typed tuple of results.
|
|
11977
|
+
* Each query preserves its own result type, projection, filtering,
|
|
11978
|
+
* sorting, and pagination.
|
|
11979
|
+
*
|
|
11980
|
+
* Read-only — use `bulkCreate`, `bulkInsert`, etc. for write batching.
|
|
11981
|
+
*
|
|
11982
|
+
* @example
|
|
11983
|
+
* ```typescript
|
|
11984
|
+
* const [people, companies] = await store.batch(
|
|
11985
|
+
* store.query()
|
|
11986
|
+
* .from("Person", "p")
|
|
11987
|
+
* .select((ctx) => ({ id: ctx.p.id, name: ctx.p.name })),
|
|
11988
|
+
* store.query()
|
|
11989
|
+
* .from("Company", "c")
|
|
11990
|
+
* .select((ctx) => ({ id: ctx.c.id, name: ctx.c.name }))
|
|
11991
|
+
* .orderBy("c", "name", "asc")
|
|
11992
|
+
* .limit(5),
|
|
11993
|
+
* );
|
|
11994
|
+
* // people: readonly { id: string; name: string }[]
|
|
11995
|
+
* // companies: readonly { id: string; name: string }[]
|
|
11996
|
+
* ```
|
|
11997
|
+
*
|
|
11998
|
+
* @param queries - Two or more executable queries (from `.select()` or set operations)
|
|
11999
|
+
* @returns A tuple with per-query typed results, preserving input order
|
|
12000
|
+
*/
|
|
12001
|
+
async batch(...queries) {
|
|
12002
|
+
return this.#backend.transaction(async (txBackend) => {
|
|
12003
|
+
const results = [];
|
|
12004
|
+
for (const query of queries) {
|
|
12005
|
+
const result = await query.executeOn(txBackend);
|
|
12006
|
+
results.push(result);
|
|
12007
|
+
}
|
|
12008
|
+
return results;
|
|
12009
|
+
});
|
|
12010
|
+
}
|
|
11559
12011
|
// === Subgraph Extraction ===
|
|
11560
12012
|
/**
|
|
11561
12013
|
* Extracts a typed subgraph by traversing from a root node.
|
|
@@ -11581,6 +12033,7 @@ var Store = class {
|
|
|
11581
12033
|
*/
|
|
11582
12034
|
async subgraph(rootId, options) {
|
|
11583
12035
|
return executeSubgraph({
|
|
12036
|
+
graph: this.#graph,
|
|
11584
12037
|
graphId: this.graphId,
|
|
11585
12038
|
rootId,
|
|
11586
12039
|
backend: this.#backend,
|
|
@@ -11942,6 +12395,7 @@ exports.createStore = createStore;
|
|
|
11942
12395
|
exports.createStoreWithSchema = createStoreWithSchema;
|
|
11943
12396
|
exports.defineEdge = defineEdge;
|
|
11944
12397
|
exports.defineNode = defineNode;
|
|
12398
|
+
exports.defineSubgraphProject = defineSubgraphProject;
|
|
11945
12399
|
exports.differentFrom = differentFrom;
|
|
11946
12400
|
exports.disjointWith = disjointWith;
|
|
11947
12401
|
exports.equivalentTo = equivalentTo;
|