16
16
// under the License.
17
17
18
18
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 } ;
20
20
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
+ } ;
22
25
23
26
impl < S : ContextProvider > SqlToRel < ' _ , S > {
24
27
#[ cfg_attr( feature = "recursive_protection" , recursive:: recursive) ]
@@ -27,6 +30,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
27
30
set_expr : SetExpr ,
28
31
planner_context : & mut PlannerContext ,
29
32
) -> Result < LogicalPlan > {
33
+ let set_expr_span = set_expr. span ( ) ;
30
34
match set_expr {
31
35
SetExpr :: Select ( s) => self . select_to_plan ( * s, vec ! [ ] , planner_context) ,
32
36
SetExpr :: Values ( v) => self . sql_values_to_plan ( v, planner_context) ,
@@ -36,8 +40,17 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
36
40
right,
37
41
set_quantifier,
38
42
} => {
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
+ ) ?;
41
54
self . set_operation_to_plan ( op, left_plan, right_plan, set_quantifier)
42
55
}
43
56
SetExpr :: Query ( q) => self . query_to_plan ( * q, planner_context) ,
@@ -61,6 +74,44 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
61
74
}
62
75
}
63
76
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
+
64
115
pub ( super ) fn set_operation_to_plan (
65
116
& self ,
66
117
op : SetOperator ,
0 commit comments