@@ -601,6 +601,7 @@ mod tests {
601
601
use crate :: { logical_plan:: col, prelude:: JoinType } ;
602
602
use arrow:: datatypes:: SchemaRef ;
603
603
use async_trait:: async_trait;
604
+ use datafusion_expr:: expr_fn:: in_list;
604
605
605
606
fn optimize_plan ( plan : & LogicalPlan ) -> LogicalPlan {
606
607
let rule = FilterPushDown :: new ( ) ;
@@ -1506,4 +1507,174 @@ mod tests {
1506
1507
1507
1508
Ok ( ( ) )
1508
1509
}
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
+ }
1509
1680
}
0 commit comments