Skip to content

Commit 91f4e3c

Browse files
committed
feat: union with different number of columns
1 parent c3532c1 commit 91f4e3c

File tree

1 file changed

+55
-4
lines changed

1 file changed

+55
-4
lines changed

datafusion/sql/src/set_expr.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
// under the License.
1717

1818
use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
19-
use datafusion_common::{not_impl_err, Result};
19+
use datafusion_common::{not_impl_err, plan_err, Diagnostic, Result};
2020
use datafusion_expr::{LogicalPlan, LogicalPlanBuilder};
21-
use sqlparser::ast::{SetExpr, SetOperator, SetQuantifier};
21+
use sqlparser::{
22+
ast::{SetExpr, SetOperator, SetQuantifier, Spanned},
23+
tokenizer::Span,
24+
};
2225

2326
impl<S: ContextProvider> SqlToRel<'_, S> {
2427
#[cfg_attr(feature = "recursive_protection", recursive::recursive)]
@@ -27,6 +30,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
2730
set_expr: SetExpr,
2831
planner_context: &mut PlannerContext,
2932
) -> Result<LogicalPlan> {
33+
let set_expr_span = set_expr.span();
3034
match set_expr {
3135
SetExpr::Select(s) => self.select_to_plan(*s, vec![], planner_context),
3236
SetExpr::Values(v) => self.sql_values_to_plan(v, planner_context),
@@ -36,8 +40,17 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
3640
right,
3741
set_quantifier,
3842
} => {
39-
let left_plan = self.set_expr_to_plan(*left, planner_context)?;
40-
let right_plan = self.set_expr_to_plan(*right, planner_context)?;
43+
let left_plan = self.set_expr_to_plan(*left.clone(), planner_context)?;
44+
let right_plan =
45+
self.set_expr_to_plan(*right.clone(), planner_context)?;
46+
self.validate_set_expr_num_of_columns(
47+
op,
48+
&left,
49+
&right,
50+
&left_plan,
51+
&right_plan,
52+
set_expr_span,
53+
)?;
4154
self.set_operation_to_plan(op, left_plan, right_plan, set_quantifier)
4255
}
4356
SetExpr::Query(q) => self.query_to_plan(*q, planner_context),
@@ -61,6 +74,44 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
6174
}
6275
}
6376

77+
fn validate_set_expr_num_of_columns(
78+
&self,
79+
op: SetOperator,
80+
left: &SetExpr,
81+
right: &SetExpr,
82+
left_plan: &LogicalPlan,
83+
right_plan: &LogicalPlan,
84+
set_expr_span: Span,
85+
) -> Result<()> {
86+
if left_plan.schema().fields().len() == right_plan.schema().fields().len() {
87+
return Ok(());
88+
}
89+
90+
plan_err!("{} queries have different number of columns", op).map_err(|err| {
91+
err.with_diagnostic(
92+
Diagnostic::new()
93+
.with_error(
94+
format!("{} queries have different number of columns", op),
95+
set_expr_span,
96+
)
97+
.with_note(
98+
format!(
99+
"this side has {} fields",
100+
left_plan.schema().fields().len()
101+
),
102+
left.span(),
103+
)
104+
.with_note(
105+
format!(
106+
"this side has {} fields",
107+
right_plan.schema().fields().len()
108+
),
109+
right.span(),
110+
),
111+
)
112+
})
113+
}
114+
64115
pub(super) fn set_operation_to_plan(
65116
&self,
66117
op: SetOperator,

0 commit comments

Comments
 (0)