Skip to content

Commit e431525

Browse files
committed
Make FieldStats generic
1 parent 890b0c7 commit e431525

11 files changed

Lines changed: 106 additions & 113 deletions

File tree

api/src/main/java/org/apache/iceberg/expressions/InclusiveMetricsEvaluator.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -476,18 +476,18 @@ public <T> Boolean notStartsWith(Bound<T> term, Literal<T> lit) {
476476
return ROWS_MIGHT_MATCH;
477477
}
478478

479-
private boolean mayContainNull(Integer id) {
479+
private boolean mayContainNull(int id) {
480480
if (null != stats) {
481-
FieldStats stat = stats.statsFor(id);
481+
FieldStats<?> stat = stats.statsFor(id);
482482
return null == stat || null == stat.nullValueCount() || stat.nullValueCount() != 0;
483483
} else {
484484
return nullCounts == null || !nullCounts.containsKey(id) || nullCounts.get(id) != 0;
485485
}
486486
}
487487

488-
private boolean containsNullsOnly(Integer id) {
488+
private boolean containsNullsOnly(int id) {
489489
if (null != stats) {
490-
FieldStats stat = stats.statsFor(id);
490+
FieldStats<?> stat = stats.statsFor(id);
491491
return null != stat
492492
&& null != stat.valueCount()
493493
&& null != stat.nullValueCount()
@@ -501,18 +501,18 @@ private boolean containsNullsOnly(Integer id) {
501501
}
502502
}
503503

504-
private boolean containsNoNaNs(Integer id) {
504+
private boolean containsNoNaNs(int id) {
505505
if (null != stats) {
506-
FieldStats stat = stats.statsFor(id);
506+
FieldStats<?> stat = stats.statsFor(id);
507507
return null != stat && null != stat.nanValueCount() && stat.nanValueCount() == 0;
508508
} else {
509509
return nanCounts != null && nanCounts.containsKey(id) && nanCounts.get(id) == 0;
510510
}
511511
}
512512

513-
private boolean containsNaNsOnly(Integer id) {
513+
private boolean containsNaNsOnly(int id) {
514514
if (null != stats) {
515-
FieldStats stat = stats.statsFor(id);
515+
FieldStats<?> stat = stats.statsFor(id);
516516
return null != stat
517517
&& null != stat.nanValueCount()
518518
&& null != stat.valueCount()
@@ -552,10 +552,9 @@ private <T> T upperBound(Bound<T> term) {
552552
private <T> T parseLowerBound(BoundReference<T> ref) {
553553
int id = ref.fieldId();
554554
if (null != stats) {
555-
FieldStats stat = stats.statsFor(id);
555+
FieldStats<T> stat = stats.statsFor(id);
556556
if (null != stat && null != stat.lowerBound()) {
557-
// FIXME: check if type helps here
558-
return (T) stat.lowerBound();
557+
return stat.lowerBound();
559558
}
560559
} else if (lowerBounds != null && lowerBounds.containsKey(id)) {
561560
return Conversions.fromByteBuffer(ref.ref().type(), lowerBounds.get(id));
@@ -567,9 +566,9 @@ private <T> T parseLowerBound(BoundReference<T> ref) {
567566
private <T> T parseUpperBound(BoundReference<T> ref) {
568567
int id = ref.fieldId();
569568
if (null != stats) {
570-
FieldStats stat = stats.statsFor(id);
569+
FieldStats<T> stat = stats.statsFor(id);
571570
if (null != stat && null != stat.upperBound()) {
572-
return (T) stat.upperBound();
571+
return stat.upperBound();
573572
}
574573
} else if (upperBounds != null && upperBounds.containsKey(id)) {
575574
return Conversions.fromByteBuffer(ref.ref().type(), upperBounds.get(id));
@@ -602,7 +601,7 @@ private <T> T extractLowerBound(BoundExtract<T> bound) {
602601
int id = bound.ref().fieldId();
603602
VariantObject fieldLowerBounds = null;
604603
if (null != stats) {
605-
FieldStats stat = stats.statsFor(id);
604+
FieldStats<?> stat = stats.statsFor(id);
606605
if (null != stat && null != stat.upperBound()) {
607606
fieldLowerBounds = parseBounds((ByteBuffer) stat.lowerBound());
608607
}
@@ -621,7 +620,7 @@ private <T> T extractUpperBound(BoundExtract<T> bound) {
621620
int id = bound.ref().fieldId();
622621
VariantObject fieldUpperBounds = null;
623622
if (null != stats) {
624-
FieldStats stat = stats.statsFor(id);
623+
FieldStats<?> stat = stats.statsFor(id);
625624
if (null != stat && null != stat.upperBound()) {
626625
fieldUpperBounds = parseBounds((ByteBuffer) stat.upperBound());
627626
}

api/src/main/java/org/apache/iceberg/expressions/StrictMetricsEvaluator.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -469,28 +469,28 @@ private boolean isNestedColumn(int id) {
469469
return struct.field(id) == null;
470470
}
471471

472-
private boolean canContainNulls(Integer id) {
472+
private boolean canContainNulls(int id) {
473473
if (null != stats) {
474-
FieldStats stat = stats.statsFor(id);
474+
FieldStats<?> stat = stats.statsFor(id);
475475
return null == stat || (null != stat.nullValueCount() && stat.nullValueCount() > 0);
476476
} else {
477477
return nullCounts == null || (nullCounts.containsKey(id) && nullCounts.get(id) > 0);
478478
}
479479
}
480480

481-
private boolean canContainNaNs(Integer id) {
481+
private boolean canContainNaNs(int id) {
482482
// nan counts might be null for early version writers when nan counters are not populated.
483483
if (null != stats) {
484-
FieldStats stat = stats.statsFor(id);
484+
FieldStats<?> stat = stats.statsFor(id);
485485
return null != stat && null != stat.nanValueCount() && stat.nanValueCount() > 0;
486486
} else {
487487
return nanCounts != null && nanCounts.containsKey(id) && nanCounts.get(id) > 0;
488488
}
489489
}
490490

491-
private boolean containsNullsOnly(Integer id) {
491+
private boolean containsNullsOnly(int id) {
492492
if (null != stats) {
493-
FieldStats stat = stats.statsFor(id);
493+
FieldStats<?> stat = stats.statsFor(id);
494494
return null != stat
495495
&& null != stat.valueCount()
496496
&& null != stat.nullValueCount()
@@ -504,9 +504,9 @@ private boolean containsNullsOnly(Integer id) {
504504
}
505505
}
506506

507-
private boolean containsNaNsOnly(Integer id) {
507+
private boolean containsNaNsOnly(int id) {
508508
if (null != stats) {
509-
FieldStats stat = stats.statsFor(id);
509+
FieldStats<?> stat = stats.statsFor(id);
510510
return null != stat
511511
&& null != stat.nanValueCount()
512512
&& null != stat.valueCount()
@@ -521,7 +521,7 @@ private boolean containsNaNsOnly(Integer id) {
521521

522522
private boolean containsNoNulls(int id) {
523523
if (null != stats) {
524-
FieldStats stat = stats.statsFor(id);
524+
FieldStats<?> stat = stats.statsFor(id);
525525
return null != stat && null != stat.nullValueCount() && stat.nullValueCount() == 0;
526526
} else {
527527
return nullCounts != null && nullCounts.containsKey(id) && nullCounts.get(id) == 0;
@@ -530,7 +530,7 @@ private boolean containsNoNulls(int id) {
530530

531531
private boolean containsNoNaNs(int id) {
532532
if (null != stats) {
533-
FieldStats stat = stats.statsFor(id);
533+
FieldStats<?> stat = stats.statsFor(id);
534534
return null != stat && null != stat.nanValueCount() && stat.nanValueCount() == 0;
535535
} else {
536536
return nanCounts != null && nanCounts.containsKey(id) && nanCounts.get(id) == 0;
@@ -540,10 +540,9 @@ private boolean containsNoNaNs(int id) {
540540
private <T> T lowerBound(BoundReference<T> ref) {
541541
int id = ref.fieldId();
542542
if (null != stats) {
543-
FieldStats stat = stats.statsFor(id);
543+
FieldStats<T> stat = stats.statsFor(id);
544544
if (null != stat && null != stat.lowerBound()) {
545-
// FIXME: check if type helps here
546-
return (T) stat.lowerBound();
545+
return stat.lowerBound();
547546
}
548547
} else if (lowerBounds != null && lowerBounds.containsKey(id)) {
549548
return Conversions.fromByteBuffer(ref.ref().type(), lowerBounds.get(id));
@@ -555,9 +554,9 @@ private <T> T lowerBound(BoundReference<T> ref) {
555554
private <T> T upperBound(BoundReference<T> ref) {
556555
int id = ref.fieldId();
557556
if (null != stats) {
558-
FieldStats stat = stats.statsFor(id);
557+
FieldStats<T> stat = stats.statsFor(id);
559558
if (null != stat && null != stat.upperBound()) {
560-
return (T) stat.upperBound();
559+
return stat.upperBound();
561560
}
562561
} else if (upperBounds != null && upperBounds.containsKey(id)) {
563562
return Conversions.fromByteBuffer(ref.ref().type(), upperBounds.get(id));

api/src/main/java/org/apache/iceberg/stats/ContentStats.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.apache.iceberg.StructLike;
2323

2424
public interface ContentStats extends StructLike {
25-
List<FieldStats> fieldStats();
25+
List<FieldStats<?>> fieldStats();
2626

27-
FieldStats statsFor(int columnId);
27+
<T> FieldStats<T> statsFor(int columnId);
2828
}

api/src/main/java/org/apache/iceberg/stats/FieldStats.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import org.apache.iceberg.StructLike;
2222
import org.apache.iceberg.types.Type;
2323

24-
public interface FieldStats extends StructLike {
24+
public interface FieldStats<T> extends StructLike {
2525
int fieldId();
2626

2727
Type type();
@@ -34,7 +34,7 @@ public interface FieldStats extends StructLike {
3434

3535
Long nanValueCount();
3636

37-
Object lowerBound();
37+
T lowerBound();
3838

39-
Object upperBound();
39+
T upperBound();
4040
}

core/src/main/java/org/apache/iceberg/stats/BaseContentStats.java

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535

3636
public class BaseContentStats implements ContentStats, StructLike, Serializable {
3737

38-
private final List<FieldStats> fieldStats;
39-
private final Map<Integer, FieldStats> fieldStatsById;
38+
private final List<FieldStats<?>> fieldStats;
39+
private final Map<Integer, FieldStats<?>> fieldStatsById;
4040

4141
public BaseContentStats(Types.StructType projection) {
4242
this.fieldStats = Lists.newArrayListWithCapacity(projection.fields().size());
@@ -60,25 +60,26 @@ public BaseContentStats(Types.StructType projection) {
6060
}
6161
}
6262

63-
private BaseContentStats(List<FieldStats> fieldStats) {
63+
private BaseContentStats(List<FieldStats<?>> fieldStats) {
6464
this.fieldStats = Lists.newArrayList(fieldStats);
6565
this.fieldStatsById = Maps.newLinkedHashMapWithExpectedSize(fieldStats.size());
6666
}
6767

6868
@Override
69-
public List<FieldStats> fieldStats() {
69+
public List<FieldStats<?>> fieldStats() {
7070
return fieldStats;
7171
}
7272

73+
@SuppressWarnings("unchecked")
7374
@Override
74-
public FieldStats statsFor(int columnId) {
75+
public <T> FieldStats<T> statsFor(int columnId) {
7576
if (fieldStatsById.isEmpty() && !fieldStats.isEmpty()) {
7677
fieldStats.stream()
7778
.filter(Objects::nonNull)
7879
.forEach(stat -> fieldStatsById.put(stat.fieldId(), stat));
7980
}
8081

81-
return fieldStatsById.get(columnId);
82+
return (FieldStats<T>) fieldStatsById.get(columnId);
8283
}
8384

8485
@Override
@@ -95,11 +96,12 @@ public <T> T get(int pos, Class<T> javaClass) {
9596
return javaClass.cast(fieldStats.get(pos));
9697
}
9798

99+
@SuppressWarnings("unchecked")
98100
@Override
99101
public <T> void set(int pos, T value) {
100102
if (value instanceof GenericRecord) {
101103
GenericRecord record = (GenericRecord) value;
102-
BaseFieldStats stat = (BaseFieldStats) fieldStats.get(pos);
104+
FieldStats<?> stat = fieldStats.get(pos);
103105
BaseFieldStats.Builder builder = BaseFieldStats.buildFrom(stat);
104106
Type type = stat.type();
105107
if (null != record.getField("column_size")) {
@@ -118,25 +120,19 @@ public <T> void set(int pos, T value) {
118120
builder.nullValueCount((Long) record.getField("null_value_count"));
119121
}
120122

121-
if (null != record.getField("lower_bound")) {
122-
Object lowerBound = record.getField("lower_bound");
123-
if (null != type) {
124-
builder.lowerBound(type.typeId().javaClass().cast(lowerBound));
125-
}
123+
if (null != record.getField("lower_bound") && null != type) {
124+
builder.lowerBound(type.typeId().javaClass().cast(record.getField("lower_bound")));
126125
}
127126

128-
if (null != record.getField("upper_bound")) {
129-
Object upperBound = record.getField("upper_bound");
130-
if (null != type) {
131-
builder.upperBound(type.typeId().javaClass().cast(upperBound));
132-
}
127+
if (null != record.getField("upper_bound") && null != type) {
128+
builder.upperBound(type.typeId().javaClass().cast(record.getField("upper_bound")));
133129
}
134130

135-
BaseFieldStats newStat = builder.build();
131+
BaseFieldStats<?> newStat = builder.build();
136132
fieldStats.set(pos, newStat);
137133
fieldStatsById.put(newStat.fieldId(), newStat);
138134
} else {
139-
fieldStats.set(pos, (FieldStats) value);
135+
fieldStats.set(pos, (FieldStats<?>) value);
140136
}
141137
}
142138

@@ -181,16 +177,16 @@ public static Builder buildFrom(ContentStats stats, Set<Integer> requestedColumn
181177
}
182178

183179
public static class Builder {
184-
private final List<FieldStats> stats = Lists.newArrayList();
180+
private final List<FieldStats<?>> stats = Lists.newArrayList();
185181

186182
private Builder() {}
187183

188-
public Builder withFieldStats(FieldStats fieldStats) {
184+
public Builder withFieldStats(FieldStats<?> fieldStats) {
189185
stats.add(fieldStats);
190186
return this;
191187
}
192188

193-
public Builder withFieldStats(List<FieldStats> fieldStats) {
189+
public Builder withFieldStats(List<FieldStats<?>> fieldStats) {
194190
stats.addAll(fieldStats);
195191
return this;
196192
}

0 commit comments

Comments
 (0)