@@ -42,14 +42,17 @@ public class PartitionPredicateHelper {
4242
4343 /**
4444 * Build a partition-typed predicate from a string-based leaf predicate on the "partition"
45- * column.
45+ * column. Only Equal and In predicates are supported for pushdown.
4646 *
47- * @return the predicate on partition fields, or {@code null} if the partition spec is invalid
48- * (indicating no results should be returned )
47+ * @return the predicate on partition fields, or {@code null} if the predicate cannot be pushed
48+ * down (unsupported predicate type or invalid partition spec )
4949 */
5050 @ Nullable
5151 public static Predicate buildPartitionPredicate (
52- LeafPredicate partitionPredicate , List <String > partitionKeys , RowType partitionType ) {
52+ LeafPredicate partitionPredicate ,
53+ List <String > partitionKeys ,
54+ RowType partitionType ,
55+ String defaultPartitionName ) {
5356 if (partitionPredicate .function () instanceof Equal ) {
5457 LinkedHashMap <String , String > partSpec =
5558 parsePartitionSpec (
@@ -60,10 +63,13 @@ public static Predicate buildPartitionPredicate(
6063 PredicateBuilder partBuilder = new PredicateBuilder (partitionType );
6164 List <Predicate > predicates = new ArrayList <>();
6265 for (int i = 0 ; i < partitionKeys .size (); i ++) {
63- Object value =
64- TypeUtils .castFromString (
65- partSpec .get (partitionKeys .get (i )), partitionType .getTypeAt (i ));
66- predicates .add (partBuilder .equal (i , value ));
66+ String strValue = partSpec .get (partitionKeys .get (i ));
67+ if (defaultPartitionName .equals (strValue )) {
68+ predicates .add (partBuilder .isNull (i ));
69+ } else {
70+ Object value = TypeUtils .castFromString (strValue , partitionType .getTypeAt (i ));
71+ predicates .add (partBuilder .equal (i , value ));
72+ }
6773 }
6874 return PredicateBuilder .and (predicates );
6975 } else if (partitionPredicate .function () instanceof In ) {
@@ -77,15 +83,22 @@ public static Predicate buildPartitionPredicate(
7783 }
7884 List <Predicate > andPredicates = new ArrayList <>();
7985 for (int i = 0 ; i < partitionKeys .size (); i ++) {
80- Object value =
81- TypeUtils .castFromString (
82- partSpec .get (partitionKeys .get (i )), partitionType .getTypeAt (i ));
83- andPredicates .add (partBuilder .equal (i , value ));
86+ String strValue = partSpec .get (partitionKeys .get (i ));
87+ if (defaultPartitionName .equals (strValue )) {
88+ andPredicates .add (partBuilder .isNull (i ));
89+ } else {
90+ Object value =
91+ TypeUtils .castFromString (strValue , partitionType .getTypeAt (i ));
92+ andPredicates .add (partBuilder .equal (i , value ));
93+ }
8494 }
8595 orPredicates .add (PredicateBuilder .and (andPredicates ));
8696 }
8797 return orPredicates .isEmpty () ? null : PredicateBuilder .or (orPredicates );
88- } else if (partitionPredicate .function () instanceof LeafBinaryFunction ) {
98+ }
99+ // Range predicates (>, >=, <, <=) can be pushed down for simple value formats
100+ // used by BucketsTable, FilesTable, FileKeyRangesTable.
101+ if (partitionPredicate .function () instanceof LeafBinaryFunction ) {
89102 LinkedHashMap <String , String > partSpec =
90103 parsePartitionSpec (
91104 partitionPredicate .literals ().get (0 ).toString (), partitionKeys );
@@ -95,16 +108,19 @@ public static Predicate buildPartitionPredicate(
95108 PredicateBuilder partBuilder = new PredicateBuilder (partitionType );
96109 List <Predicate > predicates = new ArrayList <>();
97110 for (int i = 0 ; i < partitionKeys .size (); i ++) {
98- Object value =
99- TypeUtils .castFromString (
100- partSpec .get (partitionKeys .get (i )), partitionType .getTypeAt (i ));
101- predicates .add (
102- new LeafPredicate (
103- partitionPredicate .function (),
104- partitionType .getTypeAt (i ),
105- i ,
106- partitionKeys .get (i ),
107- Collections .singletonList (value )));
111+ String strValue = partSpec .get (partitionKeys .get (i ));
112+ if (defaultPartitionName .equals (strValue )) {
113+ predicates .add (partBuilder .isNull (i ));
114+ } else {
115+ Object value = TypeUtils .castFromString (strValue , partitionType .getTypeAt (i ));
116+ predicates .add (
117+ new LeafPredicate (
118+ partitionPredicate .function (),
119+ partitionType .getTypeAt (i ),
120+ i ,
121+ partitionKeys .get (i ),
122+ Collections .singletonList (value )));
123+ }
108124 }
109125 return PredicateBuilder .and (predicates );
110126 }
@@ -115,13 +131,15 @@ public static boolean applyPartitionFilter(
115131 SnapshotReader snapshotReader ,
116132 @ Nullable LeafPredicate partitionPredicate ,
117133 List <String > partitionKeys ,
118- RowType partitionType ) {
134+ RowType partitionType ,
135+ String defaultPartitionName ) {
119136 if (partitionPredicate == null ) {
120137 return true ;
121138 }
122139
123140 Predicate predicate =
124- buildPartitionPredicate (partitionPredicate , partitionKeys , partitionType );
141+ buildPartitionPredicate (
142+ partitionPredicate , partitionKeys , partitionType , defaultPartitionName );
125143 if (predicate == null ) {
126144 return false ;
127145 }
0 commit comments