@@ -154,6 +154,8 @@ pub enum LogicalPlan {
154154 /// Unnest a column that contains a nested list type such as an
155155 /// ARRAY. This is used to implement SQL `UNNEST`
156156 Unnest ( Unnest ) ,
157+ /// A variadic query (e.g. "Recursive CTEs")
158+ RecursiveQuery ( RecursiveQuery ) ,
157159}
158160
159161impl LogicalPlan {
@@ -191,6 +193,10 @@ impl LogicalPlan {
191193 LogicalPlan :: Copy ( CopyTo { input, .. } ) => input. schema ( ) ,
192194 LogicalPlan :: Ddl ( ddl) => ddl. schema ( ) ,
193195 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+ }
194200 }
195201 }
196202
@@ -243,6 +249,10 @@ impl LogicalPlan {
243249 | LogicalPlan :: TableScan ( _) => {
244250 vec ! [ self . schema( ) ]
245251 }
252+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
253+ // return only the schema of the static term
254+ static_term. all_schemas ( )
255+ }
246256 // return children schemas
247257 LogicalPlan :: Limit ( _)
248258 | LogicalPlan :: Subquery ( _)
@@ -384,6 +394,7 @@ impl LogicalPlan {
384394 . try_for_each ( f) ,
385395 // plans without expressions
386396 LogicalPlan :: EmptyRelation ( _)
397+ | LogicalPlan :: RecursiveQuery ( _)
387398 | LogicalPlan :: Subquery ( _)
388399 | LogicalPlan :: SubqueryAlias ( _)
389400 | LogicalPlan :: Limit ( _)
@@ -430,6 +441,11 @@ impl LogicalPlan {
430441 LogicalPlan :: Ddl ( ddl) => ddl. inputs ( ) ,
431442 LogicalPlan :: Unnest ( Unnest { input, .. } ) => vec ! [ input] ,
432443 LogicalPlan :: Prepare ( Prepare { input, .. } ) => vec ! [ input] ,
444+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
445+ static_term,
446+ recursive_term,
447+ ..
448+ } ) => vec ! [ static_term, recursive_term] ,
433449 // plans without inputs
434450 LogicalPlan :: TableScan { .. }
435451 | LogicalPlan :: Statement { .. }
@@ -510,6 +526,9 @@ impl LogicalPlan {
510526 cross. left . head_output_expr ( )
511527 }
512528 }
529+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
530+ static_term. head_output_expr ( )
531+ }
513532 LogicalPlan :: Union ( union) => Ok ( Some ( Expr :: Column (
514533 union. schema . fields ( ) [ 0 ] . qualified_column ( ) ,
515534 ) ) ) ,
@@ -835,6 +854,14 @@ impl LogicalPlan {
835854 } ;
836855 Ok ( LogicalPlan :: Distinct ( distinct) )
837856 }
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+ } ) ) ,
838865 LogicalPlan :: Analyze ( a) => {
839866 assert ! ( expr. is_empty( ) ) ;
840867 assert_eq ! ( inputs. len( ) , 1 ) ;
@@ -1073,6 +1100,7 @@ impl LogicalPlan {
10731100 } ) ,
10741101 LogicalPlan :: TableScan ( TableScan { fetch, .. } ) => * fetch,
10751102 LogicalPlan :: EmptyRelation ( _) => Some ( 0 ) ,
1103+ LogicalPlan :: RecursiveQuery ( _) => None ,
10761104 LogicalPlan :: Subquery ( _) => None ,
10771105 LogicalPlan :: SubqueryAlias ( SubqueryAlias { input, .. } ) => input. max_rows ( ) ,
10781106 LogicalPlan :: Limit ( Limit { fetch, .. } ) => * fetch,
@@ -1408,6 +1436,11 @@ impl LogicalPlan {
14081436 fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
14091437 match self . 0 {
14101438 LogicalPlan :: EmptyRelation ( _) => write ! ( f, "EmptyRelation" ) ,
1439+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
1440+ is_distinct, ..
1441+ } ) => {
1442+ write ! ( f, "RecursiveQuery: is_distinct={}" , is_distinct)
1443+ }
14111444 LogicalPlan :: Values ( Values { ref values, .. } ) => {
14121445 let str_values: Vec < _ > = values
14131446 . iter ( )
@@ -1718,6 +1751,19 @@ pub struct EmptyRelation {
17181751 pub schema : DFSchemaRef ,
17191752}
17201753
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+
17211767/// Values expression. See
17221768/// [Postgres VALUES](https://www.postgresql.org/docs/current/queries-values.html)
17231769/// documentation for more details.
0 commit comments