|
33 | 33 | import org.apache.paimon.io.DataFilePathFactory; |
34 | 34 | import org.apache.paimon.manifest.FileSource; |
35 | 35 | import org.apache.paimon.predicate.Equal; |
| 36 | +import org.apache.paimon.predicate.In; |
| 37 | +import org.apache.paimon.predicate.LeafBinaryFunction; |
36 | 38 | import org.apache.paimon.predicate.LeafPredicate; |
37 | 39 | import org.apache.paimon.predicate.LeafPredicateExtractor; |
38 | 40 | import org.apache.paimon.predicate.Predicate; |
| 41 | +import org.apache.paimon.predicate.PredicateBuilder; |
39 | 42 | import org.apache.paimon.reader.RecordReader; |
40 | 43 | import org.apache.paimon.schema.SchemaManager; |
41 | 44 | import org.apache.paimon.schema.TableSchema; |
|
64 | 67 | import org.apache.paimon.utils.ProjectedRow; |
65 | 68 | import org.apache.paimon.utils.RowDataToObjectArrayConverter; |
66 | 69 | import org.apache.paimon.utils.SerializationUtils; |
| 70 | +import org.apache.paimon.utils.TypeUtils; |
67 | 71 |
|
68 | 72 | import org.apache.paimon.shade.guava30.com.google.common.collect.Iterators; |
69 | 73 |
|
@@ -193,32 +197,89 @@ public InnerTableScan withFilter(Predicate pushdown) { |
193 | 197 | @Override |
194 | 198 | public Plan innerPlan() { |
195 | 199 | SnapshotReader snapshotReader = fileStoreTable.newSnapshotReader(); |
196 | | - if (partitionPredicate != null && partitionPredicate.function() instanceof Equal) { |
197 | | - String partitionStr = partitionPredicate.literals().get(0).toString(); |
198 | | - if (partitionStr.startsWith("{")) { |
199 | | - partitionStr = partitionStr.substring(1); |
200 | | - } |
201 | | - if (partitionStr.endsWith("}")) { |
202 | | - partitionStr = partitionStr.substring(0, partitionStr.length() - 1); |
203 | | - } |
204 | | - String[] partFields = partitionStr.split(", "); |
205 | | - LinkedHashMap<String, String> partSpec = new LinkedHashMap<>(); |
| 200 | + if (partitionPredicate != null) { |
206 | 201 | List<String> partitionKeys = fileStoreTable.partitionKeys(); |
207 | | - if (partitionKeys.size() != partFields.length) { |
208 | | - return Collections::emptyList; |
209 | | - } |
210 | | - for (int i = 0; i < partitionKeys.size(); i++) { |
211 | | - partSpec.put(partitionKeys.get(i), partFields[i]); |
| 202 | + RowType partitionType = fileStoreTable.schema().logicalPartitionType(); |
| 203 | + if (partitionPredicate.function() instanceof Equal) { |
| 204 | + LinkedHashMap<String, String> partSpec = |
| 205 | + parsePartitionSpec( |
| 206 | + partitionPredicate.literals().get(0).toString(), partitionKeys); |
| 207 | + if (partSpec == null) { |
| 208 | + return Collections::emptyList; |
| 209 | + } |
| 210 | + snapshotReader.withPartitionFilter(partSpec); |
| 211 | + } else if (partitionPredicate.function() instanceof In) { |
| 212 | + List<Predicate> orPredicates = new ArrayList<>(); |
| 213 | + PredicateBuilder partBuilder = new PredicateBuilder(partitionType); |
| 214 | + for (Object literal : partitionPredicate.literals()) { |
| 215 | + LinkedHashMap<String, String> partSpec = |
| 216 | + parsePartitionSpec(literal.toString(), partitionKeys); |
| 217 | + if (partSpec == null) { |
| 218 | + continue; |
| 219 | + } |
| 220 | + List<Predicate> andPredicates = new ArrayList<>(); |
| 221 | + for (int i = 0; i < partitionKeys.size(); i++) { |
| 222 | + Object value = |
| 223 | + TypeUtils.castFromString( |
| 224 | + partSpec.get(partitionKeys.get(i)), |
| 225 | + partitionType.getTypeAt(i)); |
| 226 | + andPredicates.add(partBuilder.equal(i, value)); |
| 227 | + } |
| 228 | + orPredicates.add(PredicateBuilder.and(andPredicates)); |
| 229 | + } |
| 230 | + if (!orPredicates.isEmpty()) { |
| 231 | + snapshotReader.withPartitionFilter(PredicateBuilder.or(orPredicates)); |
| 232 | + } |
| 233 | + } else if (partitionPredicate.function() instanceof LeafBinaryFunction) { |
| 234 | + LinkedHashMap<String, String> partSpec = |
| 235 | + parsePartitionSpec( |
| 236 | + partitionPredicate.literals().get(0).toString(), partitionKeys); |
| 237 | + if (partSpec != null) { |
| 238 | + PredicateBuilder partBuilder = new PredicateBuilder(partitionType); |
| 239 | + List<Predicate> predicates = new ArrayList<>(); |
| 240 | + for (int i = 0; i < partitionKeys.size(); i++) { |
| 241 | + Object value = |
| 242 | + TypeUtils.castFromString( |
| 243 | + partSpec.get(partitionKeys.get(i)), |
| 244 | + partitionType.getTypeAt(i)); |
| 245 | + predicates.add( |
| 246 | + new LeafPredicate( |
| 247 | + partitionPredicate.function(), |
| 248 | + partitionType.getTypeAt(i), |
| 249 | + i, |
| 250 | + partitionKeys.get(i), |
| 251 | + Collections.singletonList(value))); |
| 252 | + } |
| 253 | + snapshotReader.withPartitionFilter(PredicateBuilder.and(predicates)); |
| 254 | + } |
212 | 255 | } |
213 | | - snapshotReader.withPartitionFilter(partSpec); |
214 | | - // TODO support range? |
215 | 256 | } |
216 | 257 |
|
217 | 258 | return () -> |
218 | 259 | snapshotReader.partitions().stream() |
219 | 260 | .map(p -> new FilesSplit(p, bucketPredicate, levelPredicate)) |
220 | 261 | .collect(Collectors.toList()); |
221 | 262 | } |
| 263 | + |
| 264 | + @Nullable |
| 265 | + private LinkedHashMap<String, String> parsePartitionSpec( |
| 266 | + String partitionStr, List<String> partitionKeys) { |
| 267 | + if (partitionStr.startsWith("{")) { |
| 268 | + partitionStr = partitionStr.substring(1); |
| 269 | + } |
| 270 | + if (partitionStr.endsWith("}")) { |
| 271 | + partitionStr = partitionStr.substring(0, partitionStr.length() - 1); |
| 272 | + } |
| 273 | + String[] partFields = partitionStr.split(", "); |
| 274 | + if (partitionKeys.size() != partFields.length) { |
| 275 | + return null; |
| 276 | + } |
| 277 | + LinkedHashMap<String, String> partSpec = new LinkedHashMap<>(); |
| 278 | + for (int i = 0; i < partitionKeys.size(); i++) { |
| 279 | + partSpec.put(partitionKeys.get(i), partFields[i]); |
| 280 | + } |
| 281 | + return partSpec; |
| 282 | + } |
222 | 283 | } |
223 | 284 |
|
224 | 285 | private static class FilesSplit extends SingletonSplit { |
|
0 commit comments