|
31 | 31 | import java.nio.charset.StandardCharsets; |
32 | 32 | import java.util.ArrayList; |
33 | 33 | import java.util.Collections; |
34 | | -import java.util.HashMap; |
35 | 34 | import java.util.Iterator; |
36 | 35 | import java.util.LinkedList; |
37 | 36 | import java.util.List; |
|
97 | 96 | import org.apache.iceberg.Table; |
98 | 97 | import org.apache.iceberg.avro.Avro; |
99 | 98 | import org.apache.iceberg.catalog.TableIdentifier; |
100 | | -import org.apache.iceberg.data.Record; |
101 | 99 | import org.apache.iceberg.exceptions.AlreadyExistsException; |
102 | 100 | import org.apache.iceberg.exceptions.NoSuchTableException; |
103 | | -import org.apache.iceberg.io.CloseableIterable; |
104 | 101 | import org.apache.iceberg.io.InputFile; |
105 | 102 | import org.apache.iceberg.io.OutputFile; |
106 | 103 | import org.apache.iceberg.mapping.MappingUtil; |
|
111 | 108 | import org.apache.iceberg.transforms.Transform; |
112 | 109 | import org.apache.iceberg.types.Conversions; |
113 | 110 | import org.apache.iceberg.types.Type; |
114 | | -import org.apache.iceberg.types.TypeUtil; |
115 | | -import org.apache.iceberg.types.Types; |
116 | 111 | import org.apache.parquet.hadoop.ParquetFileReader; |
117 | 112 | import org.apache.parquet.hadoop.metadata.FileMetaData; |
118 | 113 | import org.apache.parquet.hadoop.metadata.ParquetMetadata; |
@@ -573,11 +568,6 @@ private String getPartitionFromFilePath(String filePath) { |
573 | 568 | * determine the partition. We also cannot fall back to a "null" partition, because that will |
574 | 569 | * also get skipped by most queries. |
575 | 570 | * |
576 | | - * <p>The Bucket partition transform is an exceptional case because it is not monotonic, meaning |
577 | | - * it's not enough to just compare the min and max values. There may be a middle value somewhere |
578 | | - * that gets hashed to a different value. For this transform, we'll need to read all the values |
579 | | - * in the column ensure they all get transformed to the same partition value. |
580 | | - * |
581 | 571 | * <p>In these cases, we output the DataFile to the DLQ, because assigning an incorrect |
582 | 572 | * partition may lead to it being incorrectly ignored by downstream queries. |
583 | 573 | */ |
@@ -614,22 +604,9 @@ static String getPartitionFromMetrics(Metrics metrics, InputFile inputFile, Tabl |
614 | 604 |
|
615 | 605 | PartitionKey pk = new PartitionKey(table.spec(), table.schema()); |
616 | 606 |
|
617 | | - HashMap<Integer, PartitionField> bucketPartitions = new HashMap<>(); |
| 607 | + // read metadata from footer and set partition based on min/max transformed values |
618 | 608 | for (int i = 0; i < fields.size(); i++) { |
619 | 609 | PartitionField field = fields.get(i); |
620 | | - Transform<?, ?> transform = field.transform(); |
621 | | - if (transform.toString().contains("bucket[")) { |
622 | | - bucketPartitions.put(i, field); |
623 | | - } |
624 | | - } |
625 | | - |
626 | | - // first, read only metadata for the non-bucket partition types |
627 | | - for (int i = 0; i < fields.size(); i++) { |
628 | | - PartitionField field = fields.get(i); |
629 | | - // skip bucket partitions (we will process them below) |
630 | | - if (bucketPartitions.containsKey(i)) { |
631 | | - continue; |
632 | | - } |
633 | 610 | Type type = table.schema().findType(field.sourceId()); |
634 | 611 | Transform<?, ?> transform = field.transform(); |
635 | 612 |
|
@@ -658,54 +635,6 @@ static String getPartitionFromMetrics(Metrics metrics, InputFile inputFile, Tabl |
658 | 635 | pk.set(i, lowerTransformedValue); |
659 | 636 | } |
660 | 637 |
|
661 | | - // bucket transform needs extra processing (see java doc above) |
662 | | - if (!bucketPartitions.isEmpty()) { |
663 | | - // Optimize by only reading bucket-transformed columns into memory |
664 | | - org.apache.iceberg.Schema bucketCols = |
665 | | - TypeUtil.select( |
666 | | - table.schema(), |
667 | | - bucketPartitions.values().stream() |
668 | | - .map(PartitionField::sourceId) |
669 | | - .collect(Collectors.toSet())); |
670 | | - |
671 | | - // Keep one instance of transformed value per column. Use this to compare against each |
672 | | - // record's transformed value. |
673 | | - // Values in the same columns must yield the same transformed value, otherwise we cannot |
674 | | - // determine a partition |
675 | | - // from this file. |
676 | | - Map<Integer, Object> transformedValues = new HashMap<>(); |
677 | | - |
678 | | - // Do a one-time read of the file and compare all bucket-transformed columns |
679 | | - try (CloseableIterable<Record> reader = ReadUtils.createReader(inputFile, bucketCols)) { |
680 | | - for (Record record : reader) { |
681 | | - for (Map.Entry<Integer, PartitionField> entry : bucketPartitions.entrySet()) { |
682 | | - int partitionIndex = entry.getKey(); |
683 | | - PartitionField partitionField = entry.getValue(); |
684 | | - Transform<?, ?> transform = partitionField.transform(); |
685 | | - Types.NestedField field = table.schema().findField(partitionField.sourceId()); |
686 | | - Object value = record.getField(field.name()); |
687 | | - |
688 | | - // set initial transformed value for this column |
689 | | - @Nullable Object transformedValue = transformedValues.get(partitionIndex); |
690 | | - Object currentTransformedValue = transformValue(transform, field.type(), value); |
691 | | - if (transformedValue == null) { |
692 | | - transformedValues.put(partitionIndex, checkStateNotNull(currentTransformedValue)); |
693 | | - continue; |
694 | | - } |
695 | | - |
696 | | - if (!Objects.deepEquals(currentTransformedValue, transformedValue)) { |
697 | | - throw new UnknownPartitionException( |
698 | | - "Found records with conflicting transformed values, for column: " |
699 | | - + field.name()); |
700 | | - } |
701 | | - } |
702 | | - } |
703 | | - } |
704 | | - |
705 | | - for (Map.Entry<Integer, Object> partitionCol : transformedValues.entrySet()) { |
706 | | - pk.set(partitionCol.getKey(), partitionCol.getValue()); |
707 | | - } |
708 | | - } |
709 | 638 | return pk.toPath(); |
710 | 639 | } |
711 | 640 | } |
|
0 commit comments