1use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
19use datafusion_common::{
20 not_impl_err, plan_err, DataFusionError, Diagnostic, Result, Span,
21};
22use datafusion_expr::{LogicalPlan, LogicalPlanBuilder};
23use sqlparser::ast::{SetExpr, SetOperator, SetQuantifier, Spanned};
24
25impl<S: ContextProvider> SqlToRel<'_, S> {
26 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
27 pub(super) fn set_expr_to_plan(
28 &self,
29 set_expr: SetExpr,
30 planner_context: &mut PlannerContext,
31 ) -> Result<LogicalPlan> {
32 let set_expr_span = Span::try_from_sqlparser_span(set_expr.span());
33 match set_expr {
34 SetExpr::Select(s) => self.select_to_plan(*s, None, planner_context),
35 SetExpr::Values(v) => self.sql_values_to_plan(v, planner_context),
36 SetExpr::SetOperation {
37 op,
38 left,
39 right,
40 set_quantifier,
41 } => {
42 let left_span = Span::try_from_sqlparser_span(left.span());
43 let right_span = Span::try_from_sqlparser_span(right.span());
44 let left_plan = self.set_expr_to_plan(*left, planner_context);
45 let right_plan = self.set_expr_to_plan(*right, planner_context);
46 let (left_plan, right_plan) = match (left_plan, right_plan) {
47 (Ok(left_plan), Ok(right_plan)) => (left_plan, right_plan),
48 (Err(left_err), Err(right_err)) => {
49 return Err(DataFusionError::Collection(vec![
50 left_err, right_err,
51 ]));
52 }
53 (Err(err), _) | (_, Err(err)) => {
54 return Err(err);
55 }
56 };
57 if !(set_quantifier == SetQuantifier::ByName
58 || set_quantifier == SetQuantifier::AllByName)
59 {
60 self.validate_set_expr_num_of_columns(
61 op,
62 left_span,
63 right_span,
64 &left_plan,
65 &right_plan,
66 set_expr_span,
67 )?;
68 }
69 self.set_operation_to_plan(op, left_plan, right_plan, set_quantifier)
70 }
71 SetExpr::Query(q) => self.query_to_plan(*q, planner_context),
72 _ => not_impl_err!("Query {set_expr} not implemented yet"),
73 }
74 }
75
76 pub(super) fn is_union_all(set_quantifier: SetQuantifier) -> Result<bool> {
77 match set_quantifier {
78 SetQuantifier::All | SetQuantifier::AllByName => Ok(true),
79 SetQuantifier::Distinct
80 | SetQuantifier::ByName
81 | SetQuantifier::DistinctByName
82 | SetQuantifier::None => Ok(false),
83 }
84 }
85
86 fn validate_set_expr_num_of_columns(
87 &self,
88 op: SetOperator,
89 left_span: Option<Span>,
90 right_span: Option<Span>,
91 left_plan: &LogicalPlan,
92 right_plan: &LogicalPlan,
93 set_expr_span: Option<Span>,
94 ) -> Result<()> {
95 if left_plan.schema().fields().len() == right_plan.schema().fields().len() {
96 return Ok(());
97 }
98 let diagnostic = Diagnostic::new_error(
99 format!("{op} queries have different number of columns"),
100 set_expr_span,
101 )
102 .with_note(
103 format!("this side has {} fields", left_plan.schema().fields().len()),
104 left_span,
105 )
106 .with_note(
107 format!(
108 "this side has {} fields",
109 right_plan.schema().fields().len()
110 ),
111 right_span,
112 );
113 plan_err!("{} queries have different number of columns", op; diagnostic =diagnostic)
114 }
115
116 pub(super) fn set_operation_to_plan(
117 &self,
118 op: SetOperator,
119 left_plan: LogicalPlan,
120 right_plan: LogicalPlan,
121 set_quantifier: SetQuantifier,
122 ) -> Result<LogicalPlan> {
123 match (op, set_quantifier) {
124 (SetOperator::Union, SetQuantifier::All) => {
125 LogicalPlanBuilder::from(left_plan)
126 .union(right_plan)?
127 .build()
128 }
129 (SetOperator::Union, SetQuantifier::AllByName) => {
130 LogicalPlanBuilder::from(left_plan)
131 .union_by_name(right_plan)?
132 .build()
133 }
134 (SetOperator::Union, SetQuantifier::Distinct | SetQuantifier::None) => {
135 LogicalPlanBuilder::from(left_plan)
136 .union_distinct(right_plan)?
137 .build()
138 }
139 (
140 SetOperator::Union,
141 SetQuantifier::ByName | SetQuantifier::DistinctByName,
142 ) => LogicalPlanBuilder::from(left_plan)
143 .union_by_name_distinct(right_plan)?
144 .build(),
145 (SetOperator::Intersect, SetQuantifier::All) => {
146 LogicalPlanBuilder::intersect(left_plan, right_plan, true)
147 }
148 (SetOperator::Intersect, SetQuantifier::Distinct | SetQuantifier::None) => {
149 LogicalPlanBuilder::intersect(left_plan, right_plan, false)
150 }
151 (SetOperator::Except, SetQuantifier::All) => {
152 LogicalPlanBuilder::except(left_plan, right_plan, true)
153 }
154 (SetOperator::Except, SetQuantifier::Distinct | SetQuantifier::None) => {
155 LogicalPlanBuilder::except(left_plan, right_plan, false)
156 }
157 (op, quantifier) => {
158 not_impl_err!("{op} {quantifier} not implemented")
159 }
160 }
161 }
162}