MCPcopy Create free account
hub / github.com/codemix/graph / convertPattern

Function convertPattern

packages/graph/src/astToSteps.ts:1377–1521  ·  view source on GitHub ↗

* Convert a pattern into a sequence of steps. * Handles node patterns, edge patterns, and variable-length paths. * * @param pattern The pattern to convert * @param whereClause Optional WHERE clause for filtering * @param anchoredToInput If true, the first node is a reference to an existing bind

(
  pattern: Pattern,
  whereClause?: WhereClause,
  anchoredToInput: boolean = false,
  preservePriorBindings: boolean = false,
)

Source from the content-addressed store, hash-verified

1375 * to preserve variable bindings from a prior WITH clause.
1376 */
1377function convertPattern(
1378 pattern: Pattern,
1379 whereClause?: WhereClause,
1380 anchoredToInput: boolean = false,
1381 preservePriorBindings: boolean = false,
1382): Step<any>[] {
1383 const steps: Step<any>[] = [];
1384 const elements = pattern.elements;
1385
1386 if (elements.length === 0) {
1387 throw new Error("Pattern must have at least one element");
1388 }
1389
1390 // First element should be a NodePattern
1391 const firstElement = elements[0];
1392 if (firstElement?.type !== "NodePattern") {
1393 throw new Error("Pattern must start with a NodePattern");
1394 }
1395
1396 const firstNode = firstElement as NodePattern;
1397 const stepLabels = firstNode.variable ? [firstNode.variable] : undefined;
1398
1399 // Determine if this is an anchored pattern (variable reference to existing binding)
1400 // An anchored pattern has a variable but no labels and has more elements (edges)
1401 // In this case, we traverse from the input path rather than fetching all vertices.
1402 //
1403 // The heuristic only applies when anchoredToInput is explicitly true (passed from caller).
1404 // This handles cases like EXISTS { (n)-[:KNOWS]->(m) } where `n` is a bound variable.
1405 //
1406 // For fresh MATCH clauses, anchoredToInput is false, and we always create FetchVertices
1407 // even if the pattern looks like it could be anchored (e.g., MATCH (a)-[:knows]->(b)).
1408 // The label/property filter can come from the WHERE clause (e.g., WHERE a IS :Person).
1409 const isAnchorPattern =
1410 anchoredToInput &&
1411 firstNode.variable &&
1412 firstNode.labels.length === 0 &&
1413 !firstNode.labelExpression &&
1414 elements.length > 1 &&
1415 !firstNode.properties;
1416
1417 if (!isAnchorPattern) {
1418 // Create initial fetch step for pattern match
1419 // Use CartesianFetchStep if we need to preserve bindings from a prior WITH clause
1420 if (preservePriorBindings) {
1421 steps.push(
1422 new CartesianFetchStep({
1423 vertexLabels: firstNode.labels.length > 0 ? firstNode.labels : undefined,
1424 stepLabels,
1425 }),
1426 );
1427 } else {
1428 steps.push(
1429 new FetchVerticesStep({
1430 vertexLabels: firstNode.labels.length > 0 ? firstNode.labels : undefined,
1431 stepLabels,
1432 }),
1433 );
1434 }

Callers 5

processQuerySegmentsFunction · 0.85
processLegacyQueryFunction · 0.85
convertForeachClauseFunction · 0.85
convertConditionValueFunction · 0.85

Calls 7

convertLabelExpressionFunction · 0.85
convertConditionFunction · 0.85
convertEdgePatternFunction · 0.85
createNodeLabelConditionFunction · 0.85
pushMethod · 0.45

Tested by

no test coverage detected