Generate a logic plan from an SQL select
(
&self,
mut select: Select,
query_order_by: Option<OrderBy>,
planner_context: &mut PlannerContext,
)
| 74 | impl<S: ContextProvider> SqlToRel<'_, S> { |
| 75 | /// Generate a logic plan from an SQL select |
| 76 | pub(super) fn select_to_plan( |
| 77 | &self, |
| 78 | mut select: Select, |
| 79 | query_order_by: Option<OrderBy>, |
| 80 | planner_context: &mut PlannerContext, |
| 81 | ) -> Result<LogicalPlan> { |
| 82 | // Check for unsupported syntax first |
| 83 | if !select.cluster_by.is_empty() { |
| 84 | return not_impl_err!("CLUSTER BY"); |
| 85 | } |
| 86 | if !select.lateral_views.is_empty() { |
| 87 | return not_impl_err!("LATERAL VIEWS"); |
| 88 | } |
| 89 | |
| 90 | if select.top.is_some() { |
| 91 | return not_impl_err!("TOP"); |
| 92 | } |
| 93 | if !select.sort_by.is_empty() { |
| 94 | return not_impl_err!("SORT BY"); |
| 95 | } |
| 96 | |
| 97 | // Capture and clear set expression schema so it doesn't leak |
| 98 | // into subqueries planned during FROM clause handling. |
| 99 | let set_expr_left_schema = planner_context.set_set_expr_left_schema(None); |
| 100 | |
| 101 | // Process `from` clause |
| 102 | let plan = self.plan_from_tables(select.from, planner_context)?; |
| 103 | let empty_from = matches!(plan, LogicalPlan::EmptyRelation(_)); |
| 104 | |
| 105 | // Process `where` clause |
| 106 | let base_plan = self.plan_selection(select.selection, plan, planner_context)?; |
| 107 | |
| 108 | // Handle named windows before processing the projection expression |
| 109 | check_conflicting_windows(&select.named_window)?; |
| 110 | self.match_window_definitions(&mut select.projection, &select.named_window)?; |
| 111 | |
| 112 | // Process the SELECT expressions |
| 113 | let select_exprs = self.prepare_select_exprs( |
| 114 | &base_plan, |
| 115 | select.projection, |
| 116 | empty_from, |
| 117 | planner_context, |
| 118 | )?; |
| 119 | |
| 120 | // Having and group by clause may reference aliases defined in select projection |
| 121 | let projected_plan = |
| 122 | self.project(base_plan.clone(), select_exprs, set_expr_left_schema)?; |
| 123 | let select_exprs = projected_plan.expressions(); |
| 124 | |
| 125 | let order_by = |
| 126 | to_order_by_exprs_with_select(query_order_by, Some(&select_exprs))?; |
| 127 | |
| 128 | // Place the fields of the base plan at the front so that when there are references |
| 129 | // with the same name, the fields of the base plan will be searched first. |
| 130 | // See https://github.com/apache/datafusion/issues/9162 |
| 131 | let mut combined_schema = base_plan.schema().as_ref().clone(); |
| 132 | combined_schema.merge(projected_plan.schema()); |
| 133 |
no test coverage detected