| 131 | * This ensures predictable mutation ordering (e.g., MERGE before CREATE, SET before DELETE). |
| 132 | */ |
| 133 | export function astToSteps(query: Query): readonly Step<any>[] { |
| 134 | const steps: Step<any>[] = []; |
| 135 | |
| 136 | // Validation: ORDER BY, SKIP, and LIMIT require a RETURN clause |
| 137 | if (!query.return && (query.orderBy || query.skip !== undefined || query.limit !== undefined)) { |
| 138 | throw new Error("ORDER BY, SKIP, and LIMIT require a RETURN clause"); |
| 139 | } |
| 140 | |
| 141 | // If we have segments, process them in order for proper execution sequencing |
| 142 | if (query.segments && query.segments.length > 0) { |
| 143 | processQuerySegments(query.segments, steps); |
| 144 | } else if (query.return) { |
| 145 | // RETURN-only query (no segments): add StartStep to provide initial path |
| 146 | steps.push(new StartStep({})); |
| 147 | } else { |
| 148 | // Backward compatibility: use flat structure |
| 149 | processLegacyQuery(query, steps); |
| 150 | } |
| 151 | |
| 152 | // Handle ORDER BY |
| 153 | if (query.orderBy) { |
| 154 | // Build alias map from RETURN items for alias resolution |
| 155 | const aliasMap = buildReturnAliasMap(query.return); |
| 156 | const directions = query.orderBy.orders.map( |
| 157 | (order) => resolveOrderItem(order, aliasMap, false), // false = use source property/variable for RETURN ORDER BY |
| 158 | ); |
| 159 | steps.push(new OrderStep({ directions })); |
| 160 | } |
| 161 | |
| 162 | // Handle SKIP and LIMIT with RangeStep |
| 163 | if (query.skip !== undefined || query.limit !== undefined) { |
| 164 | const start = query.skip ?? 0; |
| 165 | const end = query.limit !== undefined ? start + query.limit : Number.MAX_SAFE_INTEGER; |
| 166 | steps.push(new RangeStep({ start, end })); |
| 167 | } |
| 168 | |
| 169 | // Handle RETURN clause |
| 170 | const returnSteps = convertReturnClause(query); |
| 171 | steps.push(...returnSteps); |
| 172 | |
| 173 | return steps; |
| 174 | } |
| 175 | |
| 176 | /** |
| 177 | * Process query segments in order for flexible clause ordering. |