@@ -110,6 +110,8 @@ pub enum LogicalPlan {
110
110
/// produces 0 or 1 row. This is used to implement SQL `SELECT`
111
111
/// that has no values in the `FROM` clause.
112
112
EmptyRelation ( EmptyRelation ) ,
113
+ /// A named temporary relation with a schema.
114
+ NamedRelation ( NamedRelation ) ,
113
115
/// Produces the output of running another query. This is used to
114
116
/// implement SQL subqueries
115
117
Subquery ( Subquery ) ,
@@ -152,6 +154,8 @@ pub enum LogicalPlan {
152
154
/// Unnest a column that contains a nested list type such as an
153
155
/// ARRAY. This is used to implement SQL `UNNEST`
154
156
Unnest ( Unnest ) ,
157
+ /// A variadic query (e.g. "Recursive CTEs")
158
+ RecursiveQuery ( RecursiveQuery ) ,
155
159
}
156
160
157
161
impl LogicalPlan {
@@ -188,6 +192,11 @@ impl LogicalPlan {
188
192
LogicalPlan :: Copy ( CopyTo { input, .. } ) => input. schema ( ) ,
189
193
LogicalPlan :: Ddl ( ddl) => ddl. schema ( ) ,
190
194
LogicalPlan :: Unnest ( Unnest { schema, .. } ) => schema,
195
+ LogicalPlan :: NamedRelation ( NamedRelation { 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
+ }
191
200
}
192
201
}
193
202
@@ -230,6 +239,7 @@ impl LogicalPlan {
230
239
LogicalPlan :: Explain ( _)
231
240
| LogicalPlan :: Analyze ( _)
232
241
| LogicalPlan :: EmptyRelation ( _)
242
+ | LogicalPlan :: NamedRelation ( _)
233
243
| LogicalPlan :: Ddl ( _)
234
244
| LogicalPlan :: Dml ( _)
235
245
| LogicalPlan :: Copy ( _)
@@ -240,6 +250,10 @@ impl LogicalPlan {
240
250
| LogicalPlan :: TableScan ( _) => {
241
251
vec ! [ self . schema( ) ]
242
252
}
253
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
254
+ // return only the schema of the static term
255
+ static_term. all_schemas ( )
256
+ }
243
257
// return children schemas
244
258
LogicalPlan :: Limit ( _)
245
259
| LogicalPlan :: Subquery ( _)
@@ -371,6 +385,9 @@ impl LogicalPlan {
371
385
}
372
386
// plans without expressions
373
387
LogicalPlan :: EmptyRelation ( _)
388
+ | LogicalPlan :: NamedRelation ( _)
389
+ // TODO: not sure if this should go here
390
+ | LogicalPlan :: RecursiveQuery ( _)
374
391
| LogicalPlan :: Subquery ( _)
375
392
| LogicalPlan :: SubqueryAlias ( _)
376
393
| LogicalPlan :: Limit ( _)
@@ -415,8 +432,14 @@ impl LogicalPlan {
415
432
LogicalPlan :: Ddl ( ddl) => ddl. inputs ( ) ,
416
433
LogicalPlan :: Unnest ( Unnest { input, .. } ) => vec ! [ input] ,
417
434
LogicalPlan :: Prepare ( Prepare { input, .. } ) => vec ! [ input] ,
435
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
436
+ static_term,
437
+ recursive_term,
438
+ ..
439
+ } ) => vec ! [ static_term, recursive_term] ,
418
440
// plans without inputs
419
441
LogicalPlan :: TableScan { .. }
442
+ | LogicalPlan :: NamedRelation ( _)
420
443
| LogicalPlan :: Statement { .. }
421
444
| LogicalPlan :: EmptyRelation { .. }
422
445
| LogicalPlan :: Values { .. }
@@ -492,6 +515,9 @@ impl LogicalPlan {
492
515
cross. left . head_output_expr ( )
493
516
}
494
517
}
518
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
519
+ static_term. head_output_expr ( )
520
+ }
495
521
LogicalPlan :: Union ( union) => Ok ( Some ( Expr :: Column (
496
522
union. schema . fields ( ) [ 0 ] . qualified_column ( ) ,
497
523
) ) ) ,
@@ -511,6 +537,7 @@ impl LogicalPlan {
511
537
}
512
538
LogicalPlan :: Subquery ( _) => Ok ( None ) ,
513
539
LogicalPlan :: EmptyRelation ( _)
540
+ | LogicalPlan :: NamedRelation ( _)
514
541
| LogicalPlan :: Prepare ( _)
515
542
| LogicalPlan :: Statement ( _)
516
543
| LogicalPlan :: Values ( _)
@@ -839,6 +866,14 @@ impl LogicalPlan {
839
866
input : Arc :: new ( inputs[ 0 ] . clone ( ) ) ,
840
867
} ) )
841
868
}
869
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
870
+ name, is_distinct, ..
871
+ } ) => Ok ( LogicalPlan :: RecursiveQuery ( RecursiveQuery {
872
+ name : name. clone ( ) ,
873
+ static_term : Arc :: new ( inputs[ 0 ] . clone ( ) ) ,
874
+ recursive_term : Arc :: new ( inputs[ 1 ] . clone ( ) ) ,
875
+ is_distinct : * is_distinct,
876
+ } ) ) ,
842
877
LogicalPlan :: Analyze ( a) => {
843
878
assert ! ( expr. is_empty( ) ) ;
844
879
assert_eq ! ( inputs. len( ) , 1 ) ;
@@ -877,6 +912,7 @@ impl LogicalPlan {
877
912
} ) )
878
913
}
879
914
LogicalPlan :: EmptyRelation ( _)
915
+ | LogicalPlan :: NamedRelation ( _)
880
916
| LogicalPlan :: Ddl ( _)
881
917
| LogicalPlan :: Statement ( _) => {
882
918
// All of these plan types have no inputs / exprs so should not be called
@@ -1040,6 +1076,9 @@ impl LogicalPlan {
1040
1076
} ) ,
1041
1077
LogicalPlan :: TableScan ( TableScan { fetch, .. } ) => * fetch,
1042
1078
LogicalPlan :: EmptyRelation ( _) => Some ( 0 ) ,
1079
+ // TODO: not sure if this is correct
1080
+ LogicalPlan :: NamedRelation ( _) => None ,
1081
+ LogicalPlan :: RecursiveQuery ( _) => None ,
1043
1082
LogicalPlan :: Subquery ( _) => None ,
1044
1083
LogicalPlan :: SubqueryAlias ( SubqueryAlias { input, .. } ) => input. max_rows ( ) ,
1045
1084
LogicalPlan :: Limit ( Limit { fetch, .. } ) => * fetch,
@@ -1387,6 +1426,14 @@ impl LogicalPlan {
1387
1426
fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
1388
1427
match self . 0 {
1389
1428
LogicalPlan :: EmptyRelation ( _) => write ! ( f, "EmptyRelation" ) ,
1429
+ LogicalPlan :: NamedRelation ( NamedRelation { name, .. } ) => {
1430
+ write ! ( f, "NamedRelation: {}" , name)
1431
+ }
1432
+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
1433
+ is_distinct, ..
1434
+ } ) => {
1435
+ write ! ( f, "RecursiveQuery: is_distinct={}" , is_distinct)
1436
+ }
1390
1437
LogicalPlan :: Values ( Values { ref values, .. } ) => {
1391
1438
let str_values: Vec < _ > = values
1392
1439
. iter ( )
@@ -1685,6 +1732,28 @@ pub struct EmptyRelation {
1685
1732
pub schema : DFSchemaRef ,
1686
1733
}
1687
1734
1735
+ /// A named temporary relation with a known schema.
1736
+ #[ derive( Clone , PartialEq , Eq , Hash ) ]
1737
+ pub struct NamedRelation {
1738
+ /// The relation name
1739
+ pub name : String ,
1740
+ /// The schema description
1741
+ pub schema : DFSchemaRef ,
1742
+ }
1743
+
1744
+ /// A variadic query operation
1745
+ #[ derive( Clone , PartialEq , Eq , Hash ) ]
1746
+ pub struct RecursiveQuery {
1747
+ /// Name of the query
1748
+ pub name : String ,
1749
+ /// The static term
1750
+ pub static_term : Arc < LogicalPlan > ,
1751
+ /// The recursive term
1752
+ pub recursive_term : Arc < LogicalPlan > ,
1753
+ /// Distinction
1754
+ pub is_distinct : bool ,
1755
+ }
1756
+
1688
1757
/// Values expression. See
1689
1758
/// [Postgres VALUES](https://www.postgresql.org/docs/current/queries-values.html)
1690
1759
/// documentation for more details.
0 commit comments