@@ -26,7 +26,7 @@ use crate::error::DataFusionError;
2626use crate :: logical_plan:: dfschema:: DFSchemaRef ;
2727use crate :: sql:: parser:: FileType ;
2828use arrow:: datatypes:: { DataType , Field , Schema , SchemaRef } ;
29- use datafusion_common:: DFSchema ;
29+ use datafusion_common:: { DFField , DFSchema } ;
3030use std:: fmt:: Formatter ;
3131use std:: {
3232 collections:: HashSet ,
@@ -267,22 +267,83 @@ pub struct Limit {
267267/// Evaluates correlated sub queries
268268#[ derive( Clone ) ]
269269pub struct Subquery {
270- /// The list of sub queries
271- pub subqueries : Vec < LogicalPlan > ,
272270 /// The incoming logical plan
273271 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 > ,
274276 /// The schema description of the output
275277 pub schema : DFSchemaRef ,
276278}
277279
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+
278300impl Subquery {
279301 /// 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+ }
286347 }
287348}
288349
@@ -475,13 +536,23 @@ impl LogicalPlan {
475536 LogicalPlan :: Values ( Values { schema, .. } ) => vec ! [ schema] ,
476537 LogicalPlan :: Window ( Window { input, schema, .. } )
477538 | LogicalPlan :: Projection ( Projection { input, schema, .. } )
478- | LogicalPlan :: Subquery ( Subquery { input, schema, .. } )
479539 | LogicalPlan :: Aggregate ( Aggregate { input, schema, .. } )
480540 | LogicalPlan :: TableUDFs ( TableUDFs { input, schema, .. } ) => {
481541 let mut schemas = input. all_schemas ( ) ;
482542 schemas. insert ( 0 , schema) ;
483543 schemas
484544 }
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+ }
485556 LogicalPlan :: Join ( Join {
486557 left,
487558 right,
@@ -1063,7 +1134,9 @@ impl LogicalPlan {
10631134 }
10641135 Ok ( ( ) )
10651136 }
1066- LogicalPlan :: Subquery ( Subquery { .. } ) => write ! ( f, "Subquery" ) ,
1137+ LogicalPlan :: Subquery ( Subquery { types, .. } ) => {
1138+ write ! ( f, "Subquery: types={:?}" , types)
1139+ }
10671140 LogicalPlan :: Filter ( Filter {
10681141 predicate : ref expr,
10691142 ..
0 commit comments