Repository navigation
Core: Read geometry and geography bounds as GeospatialBound #18394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,11 +22,11 @@ | |
| import java.nio.ByteBuffer; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import org.apache.iceberg.geospatial.GeospatialBound; | ||
| import org.apache.iceberg.relocated.com.google.common.base.Preconditions; | ||
| import org.apache.iceberg.types.Type; | ||
| import org.apache.iceberg.types.Types; | ||
| import org.apache.iceberg.util.ByteBuffers; | ||
| import org.apache.iceberg.util.StructLikeUtil; | ||
|
|
||
| class FieldStatsStruct<T> implements FieldStats<T>, StructLike, Serializable { | ||
| private final Types.StructType struct; | ||
|
|
@@ -231,8 +231,9 @@ private static int[] posToOffset(Types.StructType struct) { | |
| private static Object copyBound(Object bound) { | ||
| if (bound instanceof byte[] bytes) { | ||
| return copyOf(bytes); | ||
| } else if (bound instanceof StructLike struct) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the usage PartitionData and updated serialization test in TestFieldStatsStruct so that we can remove this copy branch. |
||
| return StructLikeUtil.copy(struct); | ||
| } else if (bound instanceof GeospatialBound geo) { | ||
| // readers reuse one bound instance | ||
| return geo.copy(); | ||
| } | ||
|
|
||
| return bound; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| import org.apache.iceberg.expressions.Expressions; | ||
| import org.apache.iceberg.expressions.InclusiveStatsEvaluator; | ||
| import org.apache.iceberg.expressions.Projections; | ||
| import org.apache.iceberg.geospatial.GeospatialBound; | ||
| import org.apache.iceberg.io.CloseableGroup; | ||
| import org.apache.iceberg.io.CloseableIterable; | ||
| import org.apache.iceberg.io.CloseableIterator; | ||
|
|
@@ -40,6 +41,7 @@ | |
| import org.apache.iceberg.relocated.com.google.common.collect.Maps; | ||
| import org.apache.iceberg.relocated.com.google.common.collect.Sets; | ||
| import org.apache.iceberg.types.RestoreColumns; | ||
| import org.apache.iceberg.types.Type; | ||
| import org.apache.iceberg.types.TypeUtil; | ||
| import org.apache.iceberg.types.Types; | ||
| import org.apache.iceberg.util.ArrayUtil; | ||
|
|
@@ -69,6 +71,7 @@ static Builder uncommitted( | |
| private final ManifestFile manifest; | ||
| private final ManifestBitmap dv; | ||
| private final FileIO io; | ||
| private final Schema tableSchema; | ||
| private final Schema readSchema; | ||
| private final String tableLocation; | ||
| private final InclusiveStatsEvaluator statsFilter; | ||
|
|
@@ -83,6 +86,7 @@ static Builder uncommitted( | |
| private V4ManifestReader( | ||
| ManifestFile manifest, | ||
| FileIO io, | ||
| Schema tableSchema, | ||
| Schema readSchema, | ||
| String tableLocation, | ||
| InclusiveStatsEvaluator statsFilter, | ||
|
|
@@ -94,6 +98,7 @@ private V4ManifestReader( | |
| this.manifest = manifest; | ||
| this.dv = manifest.manifestDeletionVector(); | ||
| this.io = io; | ||
| this.tableSchema = tableSchema; | ||
| this.readSchema = readSchema; | ||
| this.tableLocation = tableLocation; | ||
| this.statsFilter = statsFilter; | ||
|
|
@@ -240,6 +245,7 @@ private CloseableIterable<TrackedFile> open() { | |
| readBuilder.setCustomType(TrackedFile.CONTENT_STATS_ID, ContentStatsStruct.class); | ||
| for (Types.NestedField fieldStats : statsField.type().asStructType().fields()) { | ||
| readBuilder.setCustomType(fieldStats.fieldId(), FieldStatsStruct.class); | ||
| registerGeospatialFieldStatsBounds(readBuilder, fieldStats); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -248,6 +254,30 @@ private CloseableIterable<TrackedFile> open() { | |
| return reader; | ||
| } | ||
|
|
||
| private void registerGeospatialFieldStatsBounds( | ||
| InternalData.ReadBuilder readBuilder, Types.NestedField fieldStats) { | ||
| Types.NestedField tableField = tableSchema.findField(StatsUtil.toFieldId(fieldStats.fieldId())); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure we need the table schema for that. The stats schema should already have that information. |
||
| if (tableField == null) { | ||
| return; | ||
| } | ||
|
|
||
| Type.TypeID typeId = tableField.type().typeId(); | ||
| if (typeId != Type.TypeID.GEOMETRY && typeId != Type.TypeID.GEOGRAPHY) { | ||
| return; | ||
| } | ||
|
|
||
| Types.StructType struct = fieldStats.type().asStructType(); | ||
| setGeospatialBoundCustomType(readBuilder, struct.field(StatsUtil.LOWER_BOUND_NAME)); | ||
| setGeospatialBoundCustomType(readBuilder, struct.field(StatsUtil.UPPER_BOUND_NAME)); | ||
| } | ||
|
|
||
| private static void setGeospatialBoundCustomType( | ||
| InternalData.ReadBuilder readBuilder, Types.NestedField boundField) { | ||
| if (boundField != null) { | ||
| readBuilder.setCustomType(boundField.fieldId(), GeospatialBound.class); | ||
| } | ||
| } | ||
|
|
||
| // resolves stored locations against the table location | ||
| private TrackedFile copyResolved(TrackedFile trackedFile) { | ||
| TrackedFileStruct copy = | ||
|
|
@@ -427,6 +457,7 @@ V4ManifestReader build() { | |
| return new V4ManifestReader( | ||
| manifest, | ||
| io, | ||
| tableSchema, | ||
| readSchema(!partitionFilters.isEmpty()), | ||
| tableLocation, | ||
| statsFilter(), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe also test XYM and XYZ as the other tests do