* Convert a ShortestPathPattern into a sequence of steps. * Uses ShortestPathStep with BFS/Dijkstra algorithm. * * TODO: The pattern.all field (for allShortestPaths) currently throws an error. * Only a single shortest path is supported. Implement support for finding * all shortest paths when pa
( pattern: ShortestPathPattern, whereClause?: WhereClause, )
| 1173 | * @throws {Error} When pattern.all is true (allShortestPaths not implemented) |
| 1174 | */ |
| 1175 | function convertShortestPathPattern( |
| 1176 | pattern: ShortestPathPattern, |
| 1177 | whereClause?: WhereClause, |
| 1178 | ): Step<any>[] { |
| 1179 | // Check if allShortestPaths is requested - not yet implemented |
| 1180 | if (pattern.all === true) { |
| 1181 | throw new Error( |
| 1182 | "allShortestPaths() is not yet implemented. Use shortestPath() to find a single shortest path.", |
| 1183 | ); |
| 1184 | } |
| 1185 | |
| 1186 | const steps: Step<any>[] = []; |
| 1187 | const { source, target, edge, variable } = pattern; |
| 1188 | |
| 1189 | // Build the source vertex fetch step |
| 1190 | const sourceStepLabels = source.variable ? [source.variable] : undefined; |
| 1191 | steps.push( |
| 1192 | new FetchVerticesStep({ |
| 1193 | vertexLabels: source.labels.length > 0 ? source.labels : undefined, |
| 1194 | stepLabels: sourceStepLabels, |
| 1195 | }), |
| 1196 | ); |
| 1197 | |
| 1198 | // Apply WHERE conditions that reference the source variable |
| 1199 | let targetCondition: StepCondition | undefined; |
| 1200 | |
| 1201 | if (whereClause && source.variable) { |
| 1202 | const { early, late } = splitASTConditionByVariables(whereClause.condition, [source.variable]); |
| 1203 | |
| 1204 | // Apply early conditions to filter source vertices |
| 1205 | if (early) { |
| 1206 | steps.push(new FilterElementsStep({ condition: convertCondition(early) })); |
| 1207 | } |
| 1208 | |
| 1209 | // Extract target conditions from late conditions |
| 1210 | if (late && target.variable) { |
| 1211 | const targetVarConditions = extractConditionsForVariable(late, target.variable); |
| 1212 | if (targetVarConditions) { |
| 1213 | // Use direct property access for shortestPath target conditions |
| 1214 | // since the target vertex hasn't been bound to a variable yet |
| 1215 | targetCondition = convertCondition(targetVarConditions, true); |
| 1216 | } |
| 1217 | } |
| 1218 | } |
| 1219 | |
| 1220 | // Build target condition from target node labels and properties |
| 1221 | const targetConditions: StepCondition[] = []; |
| 1222 | |
| 1223 | // Add label conditions for target |
| 1224 | if (target.labels.length > 0) { |
| 1225 | if (target.labels.length === 1) { |
| 1226 | targetConditions.push(["=", "@label", target.labels[0]!] as StepCondition); |
| 1227 | } else { |
| 1228 | targetConditions.push([ |
| 1229 | "or", |
| 1230 | ...target.labels.map((label) => ["=", "@label", label] as StepCondition), |
| 1231 | ] as StepCondition); |
| 1232 | } |
no test coverage detected