(
&self,
with: With,
planner_context: &mut PlannerContext,
)
| 28 | |
| 29 | impl<S: ContextProvider> SqlToRel<'_, S> { |
| 30 | pub(super) fn plan_with_clause( |
| 31 | &self, |
| 32 | with: With, |
| 33 | planner_context: &mut PlannerContext, |
| 34 | ) -> Result<()> { |
| 35 | let is_recursive = with.recursive; |
| 36 | // Process CTEs from top to bottom |
| 37 | for cte in with.cte_tables { |
| 38 | // A `WITH` block can't use the same name more than once |
| 39 | let cte_name = self.ident_normalizer.normalize(cte.alias.name.clone()); |
| 40 | if planner_context.contains_cte(&cte_name) { |
| 41 | return plan_err!( |
| 42 | "WITH query name {cte_name:?} specified more than once" |
| 43 | ); |
| 44 | } |
| 45 | |
| 46 | // Create a logical plan for the CTE |
| 47 | let cte_plan = if is_recursive { |
| 48 | self.recursive_cte(&cte_name, *cte.query, planner_context)? |
| 49 | } else { |
| 50 | self.non_recursive_cte(*cte.query, planner_context)? |
| 51 | }; |
| 52 | |
| 53 | // Each `WITH` block can change the column names in the last |
| 54 | // projection (e.g. "WITH table(t1, t2) AS SELECT 1, 2"). |
| 55 | let final_plan = self.apply_table_alias(cte_plan, cte.alias)?; |
| 56 | // Export the CTE to the outer query |
| 57 | planner_context.insert_cte(cte_name, final_plan); |
| 58 | } |
| 59 | Ok(()) |
| 60 | } |
| 61 | |
| 62 | fn non_recursive_cte( |
| 63 | &self, |
no test coverage detected