@@ -110,6 +110,8 @@ pub enum LogicalPlan {
110110 /// produces 0 or 1 row. This is used to implement SQL `SELECT`
111111 /// that has no values in the `FROM` clause.
112112 EmptyRelation ( EmptyRelation ) ,
113+ /// A named temporary relation with a schema.
114+ NamedRelation ( NamedRelation ) ,
113115 /// Produces the output of running another query. This is used to
114116 /// implement SQL subqueries
115117 Subquery ( Subquery ) ,
@@ -152,6 +154,8 @@ pub enum LogicalPlan {
152154 /// Unnest a column that contains a nested list type such as an
153155 /// ARRAY. This is used to implement SQL `UNNEST`
154156 Unnest ( Unnest ) ,
157+ /// A variadic query (e.g. "Recursive CTEs")
158+ RecursiveQuery ( RecursiveQuery ) ,
155159}
156160
157161impl LogicalPlan {
@@ -188,6 +192,11 @@ impl LogicalPlan {
188192 LogicalPlan :: Copy ( CopyTo { input, .. } ) => input. schema ( ) ,
189193 LogicalPlan :: Ddl ( ddl) => ddl. schema ( ) ,
190194 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+ }
191200 }
192201 }
193202
@@ -230,6 +239,7 @@ impl LogicalPlan {
230239 LogicalPlan :: Explain ( _)
231240 | LogicalPlan :: Analyze ( _)
232241 | LogicalPlan :: EmptyRelation ( _)
242+ | LogicalPlan :: NamedRelation ( _)
233243 | LogicalPlan :: Ddl ( _)
234244 | LogicalPlan :: Dml ( _)
235245 | LogicalPlan :: Copy ( _)
@@ -240,6 +250,10 @@ impl LogicalPlan {
240250 | LogicalPlan :: TableScan ( _) => {
241251 vec ! [ self . schema( ) ]
242252 }
253+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
254+ // return only the schema of the static term
255+ static_term. all_schemas ( )
256+ }
243257 // return children schemas
244258 LogicalPlan :: Limit ( _)
245259 | LogicalPlan :: Subquery ( _)
@@ -371,6 +385,9 @@ impl LogicalPlan {
371385 }
372386 // plans without expressions
373387 LogicalPlan :: EmptyRelation ( _)
388+ | LogicalPlan :: NamedRelation ( _)
389+ // TODO: not sure if this should go here
390+ | LogicalPlan :: RecursiveQuery ( _)
374391 | LogicalPlan :: Subquery ( _)
375392 | LogicalPlan :: SubqueryAlias ( _)
376393 | LogicalPlan :: Limit ( _)
@@ -415,8 +432,14 @@ impl LogicalPlan {
415432 LogicalPlan :: Ddl ( ddl) => ddl. inputs ( ) ,
416433 LogicalPlan :: Unnest ( Unnest { input, .. } ) => vec ! [ input] ,
417434 LogicalPlan :: Prepare ( Prepare { input, .. } ) => vec ! [ input] ,
435+ LogicalPlan :: RecursiveQuery ( RecursiveQuery {
436+ static_term,
437+ recursive_term,
438+ ..
439+ } ) => vec ! [ static_term, recursive_term] ,
418440 // plans without inputs
419441 LogicalPlan :: TableScan { .. }
442+ | LogicalPlan :: NamedRelation ( _)
420443 | LogicalPlan :: Statement { .. }
421444 | LogicalPlan :: EmptyRelation { .. }
422445 | LogicalPlan :: Values { .. }
@@ -492,6 +515,9 @@ impl LogicalPlan {
492515 cross. left . head_output_expr ( )
493516 }
494517 }
518+ LogicalPlan :: RecursiveQuery ( RecursiveQuery { static_term, .. } ) => {
519+ static_term. head_output_expr ( )
520+ }
495521 LogicalPlan :: Union ( union) => Ok ( Some ( Expr :: Column (
496522 union. schema . fields ( ) [ 0 ] . qualified_column ( ) ,
497523 ) ) ) ,
@@ -511,6 +537,7 @@ impl LogicalPlan {
511537 }
512538 LogicalPlan :: Subquery ( _) => Ok ( None ) ,
513539 LogicalPlan :: EmptyRelation ( _)
540+ | LogicalPlan :: NamedRelation ( _)
514541 | LogicalPlan :: Prepare ( _)
515542 | LogicalPlan :: Statement ( _)
516543 | LogicalPlan :: Values ( _)
@@ -839,6 +866,14 @@ impl LogicalPlan {
839866 input : Arc :: new ( inputs[ 0 ] . clone ( ) ) ,
840867 } ) )
841868 }
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+ } ) ) ,
842877 LogicalPlan :: Analyze ( a) => {
843878 assert ! ( expr. is_empty( ) ) ;
844879 assert_eq ! ( inputs. len( ) , 1 ) ;
@@ -877,6 +912,7 @@ impl LogicalPlan {
877912 } ) )
878913 }
879914 LogicalPlan :: EmptyRelation ( _)
915+ | LogicalPlan :: NamedRelation ( _)
880916 | LogicalPlan :: Ddl ( _)
881917 | LogicalPlan :: Statement ( _) => {
882918 // All of these plan types have no inputs / exprs so should not be called
@@ -1040,6 +1076,9 @@ impl LogicalPlan {
10401076 } ) ,
10411077 LogicalPlan :: TableScan ( TableScan { fetch, .. } ) => * fetch,
10421078 LogicalPlan :: EmptyRelation ( _) => Some ( 0 ) ,
1079+ // TODO: not sure if this is correct
1080+ LogicalPlan :: NamedRelation ( _) => None ,
1081+ LogicalPlan :: RecursiveQuery ( _) => None ,
10431082 LogicalPlan :: Subquery ( _) => None ,
10441083 LogicalPlan :: SubqueryAlias ( SubqueryAlias { input, .. } ) => input. max_rows ( ) ,
10451084 LogicalPlan :: Limit ( Limit { fetch, .. } ) => * fetch,
@@ -1387,6 +1426,14 @@ impl LogicalPlan {
13871426 fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
13881427 match self . 0 {
13891428 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+ }
13901437 LogicalPlan :: Values ( Values { ref values, .. } ) => {
13911438 let str_values: Vec < _ > = values
13921439 . iter ( )
@@ -1685,6 +1732,28 @@ pub struct EmptyRelation {
16851732 pub schema : DFSchemaRef ,
16861733}
16871734
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+
16881757/// Values expression. See
16891758/// [Postgres VALUES](https://www.postgresql.org/docs/current/queries-values.html)
16901759/// documentation for more details.
0 commit comments