* Convert a parenthesized path pattern to steps. * Handles optional inline WHERE condition and quantifiers. * * Parenthesized path patterns allow grouping patterns with inline conditions: * - ((a)-[r]->(b) WHERE r.weight > 10) - pattern with inline condition * - ((a)-[r]->(b))+ - quantified pat
(parenthesized: ParenthesizedPathPattern)
| 1771 | * - ((a)-[r]->(b) WHERE r.weight > 10){2,5} - with condition and quantifier |
| 1772 | */ |
| 1773 | function convertParenthesizedPathPattern(parenthesized: ParenthesizedPathPattern): Step<any>[] { |
| 1774 | // Convert the inner pattern to steps WITHOUT the WHERE clause |
| 1775 | // The WHERE will be added after the pattern traversal |
| 1776 | const patternSteps = convertPattern( |
| 1777 | parenthesized.pattern, |
| 1778 | undefined, // Don't pass WHERE here, we'll add it manually |
| 1779 | true, |
| 1780 | ); |
| 1781 | |
| 1782 | // Build the complete inner steps array |
| 1783 | const innerSteps: Step<any>[] = [...patternSteps]; |
| 1784 | |
| 1785 | // Add inline WHERE condition as a filter at the end of the inner pattern |
| 1786 | // This ensures the condition is checked after each traversal iteration |
| 1787 | if (parenthesized.where) { |
| 1788 | innerSteps.push( |
| 1789 | new FilterElementsStep({ |
| 1790 | condition: convertCondition(parenthesized.where), |
| 1791 | }), |
| 1792 | ); |
| 1793 | } |
| 1794 | |
| 1795 | // If there's a quantifier, wrap in RepeatStep |
| 1796 | if (parenthesized.quantifier) { |
| 1797 | const { min, max } = parenthesized.quantifier; |
| 1798 | |
| 1799 | // Extract the last variable from the pattern for step labels |
| 1800 | const lastElement = parenthesized.pattern.elements[parenthesized.pattern.elements.length - 1]; |
| 1801 | const stepLabels = |
| 1802 | lastElement?.type === "NodePattern" && lastElement.variable |
| 1803 | ? [lastElement.variable] |
| 1804 | : undefined; |
| 1805 | |
| 1806 | // Handle zero-min case |
| 1807 | const emitInput = min === 0; |
| 1808 | const effectiveMin = min ?? 1; |
| 1809 | const emitStart = effectiveMin > 0 ? effectiveMin : 1; |
| 1810 | |
| 1811 | // Exact count |
| 1812 | if (max !== undefined && effectiveMin === max) { |
| 1813 | if (emitInput) { |
| 1814 | return [new RepeatStep({ times: max, stepLabels, emitInput }, innerSteps)]; |
| 1815 | } |
| 1816 | return [new RepeatStep({ times: max, stepLabels }, innerSteps)]; |
| 1817 | } |
| 1818 | |
| 1819 | // Range |
| 1820 | if (max !== undefined) { |
| 1821 | return [ |
| 1822 | new RepeatStep({ times: max, emit: true, emitStart, emitInput, stepLabels }, innerSteps), |
| 1823 | ]; |
| 1824 | } |
| 1825 | |
| 1826 | // Open-ended |
| 1827 | return [ |
| 1828 | new RepeatStep({ times: 100, emit: true, emitStart, emitInput, stepLabels }, innerSteps), |
| 1829 | ]; |
| 1830 | } |
no test coverage detected