Replace scans on `cte_name` with the CTE's actual subquery plan.
(plan: &SqlPlan, cte_name: &str, cte_plan: &SqlPlan)
| 275 | |
| 276 | /// Replace scans on `cte_name` with the CTE's actual subquery plan. |
| 277 | pub(super) fn inline_cte(plan: &SqlPlan, cte_name: &str, cte_plan: &SqlPlan) -> SqlPlan { |
| 278 | match plan { |
| 279 | // Direct scan on CTE name → replace with CTE plan. |
| 280 | SqlPlan::Scan { |
| 281 | collection, |
| 282 | filters, |
| 283 | projection, |
| 284 | sort_keys, |
| 285 | limit, |
| 286 | offset, |
| 287 | distinct, |
| 288 | .. |
| 289 | } if collection == cte_name => { |
| 290 | // If the outer query adds filters/sort/limit, wrap the CTE plan. |
| 291 | // For simple SELECT * FROM cte, just return the CTE plan directly. |
| 292 | if filters.is_empty() |
| 293 | && sort_keys.is_empty() |
| 294 | && limit.is_none() |
| 295 | && !distinct |
| 296 | && projection.is_empty() |
| 297 | { |
| 298 | cte_plan.clone() |
| 299 | } else { |
| 300 | // Merge outer constraints onto the CTE plan if it's also a Scan. |
| 301 | if let SqlPlan::Scan { |
| 302 | collection: inner_col, |
| 303 | alias: inner_alias, |
| 304 | engine: inner_eng, |
| 305 | filters: inner_f, |
| 306 | projection: inner_p, |
| 307 | sort_keys: inner_s, |
| 308 | limit: inner_l, |
| 309 | offset: inner_o, |
| 310 | distinct: inner_d, |
| 311 | window_functions: inner_w, |
| 312 | temporal: inner_t, |
| 313 | } = cte_plan |
| 314 | { |
| 315 | let mut merged_filters = inner_f.clone(); |
| 316 | merged_filters.extend(filters.iter().cloned()); |
| 317 | SqlPlan::Scan { |
| 318 | collection: inner_col.clone(), |
| 319 | alias: inner_alias.clone(), |
| 320 | engine: *inner_eng, |
| 321 | filters: merged_filters, |
| 322 | // Outer projection overrides inner; empty means "inherit from CTE". |
| 323 | projection: if projection.is_empty() { |
| 324 | inner_p.clone() |
| 325 | } else { |
| 326 | projection.clone() |
| 327 | }, |
| 328 | sort_keys: if sort_keys.is_empty() { |
| 329 | inner_s.clone() |
| 330 | } else { |
| 331 | sort_keys.clone() |
| 332 | }, |
| 333 | limit: limit.or(*inner_l), |
| 334 | // offset 0 = unspecified → inherit CTE's offset. |