@@ -601,6 +601,7 @@ mod tests {
601601 use crate :: { logical_plan:: col, prelude:: JoinType } ;
602602 use arrow:: datatypes:: SchemaRef ;
603603 use async_trait:: async_trait;
604+ use datafusion_expr:: expr_fn:: in_list;
604605
605606 fn optimize_plan ( plan : & LogicalPlan ) -> LogicalPlan {
606607 let rule = FilterPushDown :: new ( ) ;
@@ -1506,4 +1507,174 @@ mod tests {
15061507
15071508 Ok ( ( ) )
15081509 }
1510+
1511+ #[ test]
1512+ fn test_filter_with_alias ( ) -> Result < ( ) > {
1513+ // in table scan the true col name is 'test.a',
1514+ // but we rename it as 'b', and use col 'b' in filter
1515+ // we need rewrite filter col before push down.
1516+ let table_scan = test_table_scan ( ) ?;
1517+ let plan = LogicalPlanBuilder :: from ( table_scan)
1518+ . project ( vec ! [ col( "a" ) . alias( "b" ) , col( "c" ) ] ) ?
1519+ . filter ( and ( col ( "b" ) . gt ( lit ( 10i64 ) ) , col ( "c" ) . gt ( lit ( 10i64 ) ) ) ) ?
1520+ . build ( ) ?;
1521+
1522+ // filter on col b
1523+ assert_eq ! (
1524+ format!( "{:?}" , plan) ,
1525+ "\
1526+ Filter: #b > Int64(10) AND #test.c > Int64(10)\
1527+ \n Projection: #test.a AS b, #test.c\
1528+ \n TableScan: test projection=None\
1529+ "
1530+ ) ;
1531+
1532+ // rewrite filter col b to test.a
1533+ let expected = "\
1534+ Projection: #test.a AS b, #test.c\
1535+ \n Filter: #test.a > Int64(10) AND #test.c > Int64(10)\
1536+ \n TableScan: test projection=None\
1537+ ";
1538+
1539+ assert_optimized_plan_eq ( & plan, expected) ;
1540+
1541+ Ok ( ( ) )
1542+ }
1543+
1544+ #[ test]
1545+ fn test_filter_with_alias_2 ( ) -> Result < ( ) > {
1546+ // in table scan the true col name is 'test.a',
1547+ // but we rename it as 'b', and use col 'b' in filter
1548+ // we need rewrite filter col before push down.
1549+ let table_scan = test_table_scan ( ) ?;
1550+ let plan = LogicalPlanBuilder :: from ( table_scan)
1551+ . project ( vec ! [ col( "a" ) . alias( "b" ) , col( "c" ) ] ) ?
1552+ . project ( vec ! [ col( "b" ) , col( "c" ) ] ) ?
1553+ . filter ( and ( col ( "b" ) . gt ( lit ( 10i64 ) ) , col ( "c" ) . gt ( lit ( 10i64 ) ) ) ) ?
1554+ . build ( ) ?;
1555+
1556+ // filter on col b
1557+ assert_eq ! (
1558+ format!( "{:?}" , plan) ,
1559+ "\
1560+ Filter: #b > Int64(10) AND #test.c > Int64(10)\
1561+ \n Projection: #b, #test.c\
1562+ \n Projection: #test.a AS b, #test.c\
1563+ \n TableScan: test projection=None\
1564+ "
1565+ ) ;
1566+
1567+ // rewrite filter col b to test.a
1568+ let expected = "\
1569+ Projection: #b, #test.c\
1570+ \n Projection: #test.a AS b, #test.c\
1571+ \n Filter: #test.a > Int64(10) AND #test.c > Int64(10)\
1572+ \n TableScan: test projection=None\
1573+ ";
1574+
1575+ assert_optimized_plan_eq ( & plan, expected) ;
1576+
1577+ Ok ( ( ) )
1578+ }
1579+
1580+ #[ test]
1581+ fn test_filter_with_multi_alias ( ) -> Result < ( ) > {
1582+ let table_scan = test_table_scan ( ) ?;
1583+ let plan = LogicalPlanBuilder :: from ( table_scan)
1584+ . project ( vec ! [ col( "a" ) . alias( "b" ) , col( "c" ) . alias( "d" ) ] ) ?
1585+ . filter ( and ( col ( "b" ) . gt ( lit ( 10i64 ) ) , col ( "d" ) . gt ( lit ( 10i64 ) ) ) ) ?
1586+ . build ( ) ?;
1587+
1588+ // filter on col b and d
1589+ assert_eq ! (
1590+ format!( "{:?}" , plan) ,
1591+ "\
1592+ Filter: #b > Int64(10) AND #d > Int64(10)\
1593+ \n Projection: #test.a AS b, #test.c AS d\
1594+ \n TableScan: test projection=None\
1595+ "
1596+ ) ;
1597+
1598+ // rewrite filter col b to test.a, col d to test.c
1599+ let expected = "\
1600+ Projection: #test.a AS b, #test.c AS d\
1601+ \n Filter: #test.a > Int64(10) AND #test.c > Int64(10)\
1602+ \n TableScan: test projection=None\
1603+ ";
1604+
1605+ assert_optimized_plan_eq ( & plan, expected) ;
1606+
1607+ Ok ( ( ) )
1608+ }
1609+
1610+ #[ test]
1611+ fn test_in_filter_with_alias ( ) -> Result < ( ) > {
1612+ // in table scan the true col name is 'test.a',
1613+ // but we rename it as 'b', and use col 'b' in filter
1614+ // we need rewrite filter col before push down.
1615+ let table_scan = test_table_scan ( ) ?;
1616+ let filter_value = vec ! [ lit( 1u32 ) , lit( 2u32 ) , lit( 3u32 ) , lit( 4u32 ) ] ;
1617+ let plan = LogicalPlanBuilder :: from ( table_scan)
1618+ . project ( vec ! [ col( "a" ) . alias( "b" ) , col( "c" ) ] ) ?
1619+ . filter ( in_list ( col ( "b" ) , filter_value, false ) ) ?
1620+ . build ( ) ?;
1621+
1622+ // filter on col b
1623+ assert_eq ! (
1624+ format!( "{:?}" , plan) ,
1625+ "\
1626+ Filter: #b IN ([UInt32(1), UInt32(2), UInt32(3), UInt32(4)])\
1627+ \n Projection: #test.a AS b, #test.c\
1628+ \n TableScan: test projection=None\
1629+ "
1630+ ) ;
1631+
1632+ // rewrite filter col b to test.a
1633+ let expected = "\
1634+ Projection: #test.a AS b, #test.c\
1635+ \n Filter: #test.a IN ([UInt32(1), UInt32(2), UInt32(3), UInt32(4)])\
1636+ \n TableScan: test projection=None\
1637+ ";
1638+
1639+ assert_optimized_plan_eq ( & plan, expected) ;
1640+
1641+ Ok ( ( ) )
1642+ }
1643+
1644+ #[ test]
1645+ fn test_in_filter_with_alias_2 ( ) -> Result < ( ) > {
1646+ // in table scan the true col name is 'test.a',
1647+ // but we rename it as 'b', and use col 'b' in filter
1648+ // we need rewrite filter col before push down.
1649+ let table_scan = test_table_scan ( ) ?;
1650+ let filter_value = vec ! [ lit( 1u32 ) , lit( 2u32 ) , lit( 3u32 ) , lit( 4u32 ) ] ;
1651+ let plan = LogicalPlanBuilder :: from ( table_scan)
1652+ . project ( vec ! [ col( "a" ) . alias( "b" ) , col( "c" ) ] ) ?
1653+ . project ( vec ! [ col( "b" ) , col( "c" ) ] ) ?
1654+ . filter ( in_list ( col ( "b" ) , filter_value, false ) ) ?
1655+ . build ( ) ?;
1656+
1657+ // filter on col b
1658+ assert_eq ! (
1659+ format!( "{:?}" , plan) ,
1660+ "\
1661+ Filter: #b IN ([UInt32(1), UInt32(2), UInt32(3), UInt32(4)])\
1662+ \n Projection: #b, #test.c\
1663+ \n Projection: #test.a AS b, #test.c\
1664+ \n TableScan: test projection=None\
1665+ "
1666+ ) ;
1667+
1668+ // rewrite filter col b to test.a
1669+ let expected = "\
1670+ Projection: #b, #test.c\
1671+ \n Projection: #test.a AS b, #test.c\
1672+ \n Filter: #test.a IN ([UInt32(1), UInt32(2), UInt32(3), UInt32(4)])\
1673+ \n TableScan: test projection=None\
1674+ ";
1675+
1676+ assert_optimized_plan_eq ( & plan, expected) ;
1677+
1678+ Ok ( ( ) )
1679+ }
15091680}
0 commit comments