@@ -154,6 +154,8 @@ pub enum LogicalPlan {
154
154
/// Unnest a column that contains a nested list type such as an
155
155
/// ARRAY. This is used to implement SQL `UNNEST`
156
156
Unnest ( Unnest ) ,
157
+ /// A variadic query (e.g. "Recursive CTEs")
158
+ RecursiveQuery ( RecursiveQuery ) ,
157
159
}
158
160
159
161
impl LogicalPlan {
@@ -191,6 +193,10 @@ impl LogicalPlan {
191
193
LogicalPlan :: Copy ( CopyTo { input, .. } ) => input. schema ( ) ,
192
194
LogicalPlan :: Ddl ( ddl) => ddl. schema ( ) ,
193
195
LogicalPlan :: Unnest ( Unnest { schema, .. } ) => schema,
196
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
197
+ // we take the schema of the static term as the schema of the entire recursive query
198
+ static_term. schema ( )
199
+ }
194
200
}
195
201
}
196
202
@@ -243,6 +249,10 @@ impl LogicalPlan {
243
249
| LogicalPlan :: TableScan ( _) => {
244
250
vec ! [ self . schema( ) ]
245
251
}
252
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
253
+ // return only the schema of the static term
254
+ static_term. all_schemas ( )
255
+ }
246
256
// return children schemas
247
257
LogicalPlan :: Limit ( _)
248
258
| LogicalPlan :: Subquery ( _)
@@ -384,6 +394,7 @@ impl LogicalPlan {
384
394
. try_for_each ( f) ,
385
395
// plans without expressions
386
396
LogicalPlan :: EmptyRelation ( _)
397
+ | LogicalPlan :: RecursiveQuery ( _)
387
398
| LogicalPlan :: Subquery ( _)
388
399
| LogicalPlan :: SubqueryAlias ( _)
389
400
| LogicalPlan :: Limit ( _)
@@ -430,6 +441,11 @@ impl LogicalPlan {
430
441
LogicalPlan :: Ddl ( ddl) => ddl. inputs ( ) ,
431
442
LogicalPlan :: Unnest ( Unnest { input, .. } ) => vec ! [ input] ,
432
443
LogicalPlan :: Prepare ( Prepare { input, .. } ) => vec ! [ input] ,
444
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
445
+ static_term,
446
+ recursive_term,
447
+ ..
448
+ } ) => vec ! [ static_term, recursive_term] ,
433
449
// plans without inputs
434
450
LogicalPlan :: TableScan { .. }
435
451
| LogicalPlan :: Statement { .. }
@@ -510,6 +526,9 @@ impl LogicalPlan {
510
526
cross. left . head_output_expr ( )
511
527
}
512
528
}
529
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
530
+ static_term. head_output_expr ( )
531
+ }
513
532
LogicalPlan :: Union ( union) => Ok ( Some ( Expr :: Column (
514
533
union. schema . fields ( ) [ 0 ] . qualified_column ( ) ,
515
534
) ) ) ,
@@ -835,6 +854,14 @@ impl LogicalPlan {
835
854
} ;
836
855
Ok ( LogicalPlan :: Distinct ( distinct) )
837
856
}
857
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
858
+ name, is_distinct, ..
859
+ } ) => Ok ( LogicalPlan :: RecursiveQuery ( RecursiveQuery {
860
+ name : name. clone ( ) ,
861
+ static_term : Arc :: new ( inputs[ 0 ] . clone ( ) ) ,
862
+ recursive_term : Arc :: new ( inputs[ 1 ] . clone ( ) ) ,
863
+ is_distinct : * is_distinct,
864
+ } ) ) ,
838
865
LogicalPlan :: Analyze ( a) => {
839
866
assert ! ( expr. is_empty( ) ) ;
840
867
assert_eq ! ( inputs. len( ) , 1 ) ;
@@ -1073,6 +1100,7 @@ impl LogicalPlan {
1073
1100
} ) ,
1074
1101
LogicalPlan :: TableScan ( TableScan { fetch, .. } ) => * fetch,
1075
1102
LogicalPlan :: EmptyRelation ( _) => Some ( 0 ) ,
1103
+ LogicalPlan :: RecursiveQuery ( _) => None ,
1076
1104
LogicalPlan :: Subquery ( _) => None ,
1077
1105
LogicalPlan :: SubqueryAlias ( SubqueryAlias { input, .. } ) => input. max_rows ( ) ,
1078
1106
LogicalPlan :: Limit ( Limit { fetch, .. } ) => * fetch,
@@ -1408,6 +1436,11 @@ impl LogicalPlan {
1408
1436
fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
1409
1437
match self . 0 {
1410
1438
LogicalPlan :: EmptyRelation ( _) => write ! ( f, "EmptyRelation" ) ,
1439
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
1440
+ is_distinct, ..
1441
+ } ) => {
1442
+ write ! ( f, "RecursiveQuery: is_distinct={}" , is_distinct)
1443
+ }
1411
1444
LogicalPlan :: Values ( Values { ref values, .. } ) => {
1412
1445
let str_values: Vec < _ > = values
1413
1446
. iter ( )
@@ -1718,6 +1751,19 @@ pub struct EmptyRelation {
1718
1751
pub schema : DFSchemaRef ,
1719
1752
}
1720
1753
1754
+ /// A variadic query operation
1755
+ #[ derive( Clone , PartialEq , Eq , Hash ) ]
1756
+ pub struct RecursiveQuery {
1757
+ /// Name of the query
1758
+ pub name : String ,
1759
+ /// The static term
1760
+ pub static_term : Arc < LogicalPlan > ,
1761
+ /// The recursive term
1762
+ pub recursive_term : Arc < LogicalPlan > ,
1763
+ /// Distinction
1764
+ pub is_distinct : bool ,
1765
+ }
1766
+
1721
1767
/// Values expression. See
1722
1768
/// [Postgres VALUES](https://www.postgresql.org/docs/current/queries-values.html)
1723
1769
/// documentation for more details.
0 commit comments