@@ -26,7 +26,7 @@ use crate::error::DataFusionError;
26
26
use crate :: logical_plan:: dfschema:: DFSchemaRef ;
27
27
use crate :: sql:: parser:: FileType ;
28
28
use arrow:: datatypes:: { DataType , Field , Schema , SchemaRef } ;
29
- use datafusion_common:: DFSchema ;
29
+ use datafusion_common:: { DFField , DFSchema } ;
30
30
use std:: fmt:: Formatter ;
31
31
use std:: {
32
32
collections:: HashSet ,
@@ -267,22 +267,83 @@ pub struct Limit {
267
267
/// Evaluates correlated sub queries
268
268
#[ derive( Clone ) ]
269
269
pub struct Subquery {
270
- /// The list of sub queries
271
- pub subqueries : Vec < LogicalPlan > ,
272
270
/// The incoming logical plan
273
271
pub input : Arc < LogicalPlan > ,
272
+ /// The list of sub queries
273
+ pub subqueries : Vec < LogicalPlan > ,
274
+ /// The list of subquery types
275
+ pub types : Vec < SubqueryType > ,
274
276
/// The schema description of the output
275
277
pub schema : DFSchemaRef ,
276
278
}
277
279
280
+ /// Subquery type
281
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
282
+ pub enum SubqueryType {
283
+ /// Scalar (SELECT, WHERE) evaluating to one value
284
+ Scalar ,
285
+ /// EXISTS(...) evaluating to true if at least one row was produced
286
+ Exists ,
287
+ // This will be extended with `AnyAll` type.
288
+ }
289
+
290
+ impl Display for SubqueryType {
291
+ fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
292
+ let subquery_type = match self {
293
+ SubqueryType :: Scalar => "Scalar" ,
294
+ SubqueryType :: Exists => "Exists" ,
295
+ } ;
296
+ write ! ( f, "{}" , subquery_type)
297
+ }
298
+ }
299
+
278
300
impl Subquery {
279
301
/// Merge schema of main input and correlated subquery columns
280
- pub fn merged_schema ( input : & LogicalPlan , subqueries : & [ LogicalPlan ] ) -> DFSchema {
281
- subqueries. iter ( ) . fold ( ( * * input. schema ( ) ) . clone ( ) , |a, b| {
282
- let mut res = a;
283
- res. merge ( b. schema ( ) ) ;
284
- res
285
- } )
302
+ pub fn merged_schema (
303
+ input : & LogicalPlan ,
304
+ subqueries : & [ LogicalPlan ] ,
305
+ types : & [ SubqueryType ] ,
306
+ ) -> DFSchema {
307
+ subqueries. iter ( ) . zip ( types. iter ( ) ) . fold (
308
+ ( * * input. schema ( ) ) . clone ( ) ,
309
+ |schema, ( plan, typ) | {
310
+ let mut schema = schema;
311
+ schema. merge ( & Self :: transform_dfschema ( plan. schema ( ) , * typ) ) ;
312
+ schema
313
+ } ,
314
+ )
315
+ }
316
+
317
+ /// Transform DataFusion schema according to subquery type
318
+ pub fn transform_dfschema ( schema : & DFSchema , typ : SubqueryType ) -> DFSchema {
319
+ match typ {
320
+ SubqueryType :: Scalar => schema. clone ( ) ,
321
+ SubqueryType :: Exists => {
322
+ let new_fields = schema
323
+ . fields ( )
324
+ . iter ( )
325
+ . map ( |field| {
326
+ let new_field = Subquery :: transform_field ( field. field ( ) , typ) ;
327
+ if let Some ( qualifier) = field. qualifier ( ) {
328
+ DFField :: from_qualified ( qualifier, new_field)
329
+ } else {
330
+ DFField :: from ( new_field)
331
+ }
332
+ } )
333
+ . collect ( ) ;
334
+ DFSchema :: new_with_metadata ( new_fields, schema. metadata ( ) . clone ( ) )
335
+ . unwrap ( )
336
+ } // Schema will be transformed for `AnyAll` as well
337
+ }
338
+ }
339
+
340
+ /// Transform Arrow field according to subquery type
341
+ pub fn transform_field ( field : & Field , typ : SubqueryType ) -> Field {
342
+ match typ {
343
+ SubqueryType :: Scalar => field. clone ( ) ,
344
+ SubqueryType :: Exists => Field :: new ( field. name ( ) , DataType :: Boolean , false ) ,
345
+ // Field will be transformed for `AnyAll` as well
346
+ }
286
347
}
287
348
}
288
349
@@ -475,13 +536,23 @@ impl LogicalPlan {
475
536
LogicalPlan :: Values ( Values { schema, .. } ) => vec ! [ schema] ,
476
537
LogicalPlan :: Window ( Window { input, schema, .. } )
477
538
| LogicalPlan :: Projection ( Projection { input, schema, .. } )
478
- | LogicalPlan :: Subquery ( Subquery { input, schema, .. } )
479
539
| LogicalPlan :: Aggregate ( Aggregate { input, schema, .. } )
480
540
| LogicalPlan :: TableUDFs ( TableUDFs { input, schema, .. } ) => {
481
541
let mut schemas = input. all_schemas ( ) ;
482
542
schemas. insert ( 0 , schema) ;
483
543
schemas
484
544
}
545
+ LogicalPlan :: Subquery ( Subquery {
546
+ input,
547
+ subqueries,
548
+ schema,
549
+ ..
550
+ } ) => {
551
+ let mut schemas = input. all_schemas ( ) ;
552
+ schemas. extend ( subqueries. iter ( ) . map ( |s| s. schema ( ) ) ) ;
553
+ schemas. insert ( 0 , schema) ;
554
+ schemas
555
+ }
485
556
LogicalPlan :: Join ( Join {
486
557
left,
487
558
right,
@@ -1063,7 +1134,9 @@ impl LogicalPlan {
1063
1134
}
1064
1135
Ok ( ( ) )
1065
1136
}
1066
- LogicalPlan :: Subquery ( Subquery { .. } ) => write ! ( f, "Subquery" ) ,
1137
+ LogicalPlan :: Subquery ( Subquery { types, .. } ) => {
1138
+ write ! ( f, "Subquery: types={:?}" , types)
1139
+ }
1067
1140
LogicalPlan :: Filter ( Filter {
1068
1141
predicate : ref expr,
1069
1142
..
0 commit comments