1616// under the License.
1717
1818use crate :: planner:: { ContextProvider , PlannerContext , SqlToRel } ;
19- use datafusion_common:: { not_impl_err, Result } ;
19+ use datafusion_common:: { not_impl_err, plan_err , Diagnostic , Result } ;
2020use 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
2326impl < 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