@@ -1295,21 +1295,32 @@ fn construct_prefix_orderings(
12951295 relevant_sort_expr : & PhysicalSortExpr ,
12961296 dependency_map : & DependencyMap ,
12971297) -> Vec < LexOrdering > {
1298+ let mut processed_dependencies = IndexSet :: new ( ) ;
12981299 dependency_map[ relevant_sort_expr]
12991300 . dependencies
13001301 . iter ( )
1301- . flat_map ( |dep| construct_orderings ( dep, dependency_map) )
1302+ . flat_map ( |dep| {
1303+ construct_orderings ( dep, & mut processed_dependencies, dependency_map)
1304+ } )
13021305 . collect ( )
13031306}
13041307
1305- /// Given a set of relevant dependencies (`relevant_deps`) and a map of dependencies
1306- /// (`dependency_map`), this function generates all possible prefix orderings
1307- /// based on the given dependencies.
1308+ /// Generates all possible orderings where dependencies are satisfied for the
1309+ /// current projection expression.
1310+ ///
1311+ /// # Examaple
1312+ /// If `dependences` is `a + b ASC` and the dependency map holds dependencies
1313+ /// * `a ASC` --> `[c ASC]`
1314+ /// * `b ASC` --> `[d DESC]`,
1315+ ///
1316+ /// This function generates these two sort orders
1317+ /// * `[c ASC, d DESC, a + b ASC]`
1318+ /// * `[d DESC, c ASC, a + b ASC]`
13081319///
13091320/// # Parameters
13101321///
1311- /// * `dependencies` - A reference to the dependencies .
1312- /// * `dependency_map` - A reference to the map of dependencies for expressions.
1322+ /// * `dependencies` - Set of relevant expressions .
1323+ /// * `dependency_map` - Map of dependencies for expressions that may appear in `dependencies`
13131324///
13141325/// # Returns
13151326///
@@ -1335,11 +1346,6 @@ fn generate_dependency_orderings(
13351346 return vec ! [ vec![ ] ] ;
13361347 }
13371348
1338- // Generate all possible orderings where dependencies are satisfied for the
1339- // current projection expression. For example, if expression is `a + b ASC`,
1340- // and the dependency for `a ASC` is `[c ASC]`, the dependency for `b ASC`
1341- // is `[d DESC]`, then we generate `[c ASC, d DESC, a + b ASC]` and
1342- // `[d DESC, c ASC, a + b ASC]`.
13431349 relevant_prefixes
13441350 . into_iter ( )
13451351 . multi_cartesian_product ( )
@@ -1421,7 +1427,7 @@ struct DependencyNode {
14211427}
14221428
14231429impl DependencyNode {
1424- // Insert dependency to the state (if exists).
1430+ /// Insert dependency to the state (if exists).
14251431 fn insert_dependency ( & mut self , dependency : Option < & PhysicalSortExpr > ) {
14261432 if let Some ( dep) = dependency {
14271433 self . dependencies . insert ( dep. clone ( ) ) ;
@@ -1453,10 +1459,16 @@ type Dependencies = IndexSet<PhysicalSortExpr>;
14531459///
14541460/// A vector of lexicographical orderings (`Vec<LexOrdering>`) based on the given
14551461/// sort expression and its dependencies.
1456- fn construct_orderings (
1457- referred_sort_expr : & PhysicalSortExpr ,
1458- dependency_map : & DependencyMap ,
1462+ fn construct_orderings < ' a > (
1463+ referred_sort_expr : & ' a PhysicalSortExpr ,
1464+ processed_dependencies : & mut IndexSet < & ' a PhysicalSortExpr > ,
1465+ dependency_map : & ' a DependencyMap ,
14591466) -> Vec < LexOrdering > {
1467+ // if we have already processed this dependency don't do it again
1468+ if !processed_dependencies. insert ( referred_sort_expr) {
1469+ return vec ! [ ] ;
1470+ }
1471+
14601472 // We are sure that `referred_sort_expr` is inside `dependency_map`.
14611473 let node = & dependency_map[ referred_sort_expr] ;
14621474 // Since we work on intermediate nodes, we are sure `val.target_sort_expr`
@@ -1468,7 +1480,8 @@ fn construct_orderings(
14681480 node. dependencies
14691481 . iter ( )
14701482 . flat_map ( |dep| {
1471- let mut orderings = construct_orderings ( dep, dependency_map) ;
1483+ let mut orderings =
1484+ construct_orderings ( dep, processed_dependencies, dependency_map) ;
14721485 for ordering in orderings. iter_mut ( ) {
14731486 ordering. push ( target_sort_expr. clone ( ) )
14741487 }
@@ -1763,6 +1776,50 @@ mod tests {
17631776 Ok ( ( ) )
17641777 }
17651778
1779+ #[ test]
1780+ fn project_equivalence_properties_test_multi ( ) -> Result < ( ) > {
1781+ // test multiple input orderings with equivalence properties
1782+ let input_schema = Arc :: new ( Schema :: new ( vec ! [
1783+ Field :: new( "a" , DataType :: Int64 , true ) ,
1784+ Field :: new( "b" , DataType :: Int64 , true ) ,
1785+ Field :: new( "c" , DataType :: Int64 , true ) ,
1786+ Field :: new( "d" , DataType :: Int64 , true ) ,
1787+ ] ) ) ;
1788+
1789+ let mut input_properties = EquivalenceProperties :: new ( Arc :: clone ( & input_schema) ) ;
1790+ // add equivalent ordering [a, b, c, d]
1791+ input_properties. add_new_ordering ( vec ! [
1792+ parse_sort_expr( "a" , & input_schema) ,
1793+ parse_sort_expr( "b" , & input_schema) ,
1794+ parse_sort_expr( "c" , & input_schema) ,
1795+ parse_sort_expr( "d" , & input_schema) ,
1796+ ] ) ;
1797+
1798+ // add equivalent ordering [a, c, b, d]
1799+ input_properties. add_new_ordering ( vec ! [
1800+ parse_sort_expr( "a" , & input_schema) ,
1801+ parse_sort_expr( "c" , & input_schema) ,
1802+ parse_sort_expr( "b" , & input_schema) , // NB b and c are swapped
1803+ parse_sort_expr( "d" , & input_schema) ,
1804+ ] ) ;
1805+
1806+ // simply project all the columns in order
1807+ let proj_exprs = vec ! [
1808+ ( col( "a" , & input_schema) ?, "a" . to_string( ) ) ,
1809+ ( col( "b" , & input_schema) ?, "b" . to_string( ) ) ,
1810+ ( col( "c" , & input_schema) ?, "c" . to_string( ) ) ,
1811+ ( col( "d" , & input_schema) ?, "d" . to_string( ) ) ,
1812+ ] ;
1813+ let projection_mapping = ProjectionMapping :: try_new ( & proj_exprs, & input_schema) ?;
1814+ let out_properties = input_properties. project ( & projection_mapping, input_schema) ;
1815+
1816+ assert_eq ! (
1817+ out_properties. to_string( ) ,
1818+ "order: [[a@0 ASC,b@1 ASC,c@2 ASC,d@3 ASC]]"
1819+ ) ;
1820+ Ok ( ( ) )
1821+ }
1822+
17661823 #[ test]
17671824 fn test_join_equivalence_properties ( ) -> Result < ( ) > {
17681825 let schema = create_test_schema ( ) ?;
0 commit comments