@@ -140,3 +140,85 @@ async fn union_schemas() -> Result<()> {
140
140
assert_batches_eq ! ( expected, & result) ;
141
141
Ok ( ( ) )
142
142
}
143
+
144
+ #[ tokio:: test]
145
+ async fn union_with_except_input ( ) -> Result < ( ) > {
146
+ let ctx = create_union_context ( ) ?;
147
+ let sql = "(
148
+ SELECT name FROM t1
149
+ EXCEPT
150
+ SELECT name FROM t2
151
+ )
152
+ UNION ALL
153
+ (
154
+ SELECT name FROM t2
155
+ EXCEPT
156
+ SELECT name FROM t1
157
+ )" ;
158
+ let msg = format ! ( "Creating logical plan for '{sql}'" ) ;
159
+ let dataframe = ctx. sql ( & ( "explain " . to_owned ( ) + sql) ) . await . expect ( & msg) ;
160
+ let plan = dataframe. into_optimized_plan ( ) ?;
161
+ let expected = vec ! [
162
+ "Explain [plan_type:Utf8, plan:Utf8]" ,
163
+ " Union [name:UInt8;N]" ,
164
+ " LeftAnti Join: t1.name = t2.name [name:UInt8;N]" ,
165
+ " Distinct: [name:UInt8;N]" ,
166
+ " TableScan: t1 projection=[name] [name:UInt8;N]" ,
167
+ " Projection: t2.name [name:UInt8;N]" ,
168
+ " TableScan: t2 projection=[name] [name:UInt8;N]" ,
169
+ " LeftAnti Join: t2.name = t1.name [name:UInt8;N]" ,
170
+ " Distinct: [name:UInt8;N]" ,
171
+ " TableScan: t2 projection=[name] [name:UInt8;N]" ,
172
+ " Projection: t1.name [name:UInt8;N]" ,
173
+ " TableScan: t1 projection=[name] [name:UInt8;N]" ,
174
+ ] ;
175
+
176
+ let formatted = plan. display_indent_schema ( ) . to_string ( ) ;
177
+ let actual: Vec < & str > = formatted. trim ( ) . lines ( ) . collect ( ) ;
178
+ assert_eq ! (
179
+ expected, actual,
180
+ "\n \n expected:\n \n {expected:#?}\n actual:\n \n {actual:#?}\n \n "
181
+ ) ;
182
+ Ok ( ( ) )
183
+ }
184
+
185
+ #[ tokio:: test]
186
+ async fn union_with_type_coercion ( ) -> Result < ( ) > {
187
+ let ctx = create_union_context ( ) ?;
188
+ let sql = "(
189
+ SELECT id, name FROM t1
190
+ EXCEPT
191
+ SELECT id, name FROM t2
192
+ )
193
+ UNION ALL
194
+ (
195
+ SELECT id, name FROM t2
196
+ EXCEPT
197
+ SELECT id, name FROM t1
198
+ )" ;
199
+ let msg = format ! ( "Creating logical plan for '{sql}'" ) ;
200
+ let dataframe = ctx. sql ( & ( "explain " . to_owned ( ) + sql) ) . await . expect ( & msg) ;
201
+ let plan = dataframe. into_optimized_plan ( ) ?;
202
+ let expected = vec ! [
203
+ "Explain [plan_type:Utf8, plan:Utf8]" ,
204
+ " Union [id:Int32;N, name:UInt8;N]" ,
205
+ " LeftAnti Join: t1.id = CAST(t2.id AS Int32), t1.name = t2.name [id:Int32;N, name:UInt8;N]" ,
206
+ " Distinct: [id:Int32;N, name:UInt8;N]" ,
207
+ " TableScan: t1 projection=[id, name] [id:Int32;N, name:UInt8;N]" ,
208
+ " Projection: t2.id, t2.name [id:UInt8;N, name:UInt8;N]" ,
209
+ " TableScan: t2 projection=[id, name] [id:UInt8;N, name:UInt8;N]" ,
210
+ " Projection: CAST(t2.id AS Int32) AS id, t2.name [id:Int32;N, name:UInt8;N]" ,
211
+ " LeftAnti Join: CAST(t2.id AS Int32) = t1.id, t2.name = t1.name [id:UInt8;N, name:UInt8;N]" ,
212
+ " Distinct: [id:UInt8;N, name:UInt8;N]" ,
213
+ " TableScan: t2 projection=[id, name] [id:UInt8;N, name:UInt8;N]" ,
214
+ " Projection: t1.id, t1.name [id:Int32;N, name:UInt8;N]" ,
215
+ " TableScan: t1 projection=[id, name] [id:Int32;N, name:UInt8;N]" ,
216
+ ] ;
217
+ let formatted = plan. display_indent_schema ( ) . to_string ( ) ;
218
+ let actual: Vec < & str > = formatted. trim ( ) . lines ( ) . collect ( ) ;
219
+ assert_eq ! (
220
+ expected, actual,
221
+ "\n \n expected:\n \n {expected:#?}\n actual:\n \n {actual:#?}\n \n "
222
+ ) ;
223
+ Ok ( ( ) )
224
+ }
0 commit comments