Skip to content

feat: support geometry and geography types - #2933

Open
wirybeaver wants to merge 9 commits into
apache:mainfrom
wirybeaver:support-geometry-geography-types
Open

feat: support geometry and geography types#2933
wirybeaver wants to merge 9 commits into
apache:mainfrom
wirybeaver:support-geometry-geography-types

Conversation

@wirybeaver

Copy link
Copy Markdown

Summary

This draft PR adds Iceberg Geometry/Geography primitive type support by reusing arrow-rs/parquet-geospatial support instead of introducing a local geospatial model.

  • Adds GeometryType and GeographyType with an Iceberg-owned EdgeInterpolationAlgorithm, translating to parquet_geospatial::WkbEdges at the Arrow boundary.
  • Converts Geometry/Geography to Arrow WKB extension metadata and enables Parquet geospatial logical type writing.
  • Maps Avro, Glue, and HMS representations to bytes/binary.
  • Rejects non-null JSON defaults, blocks unsupported partition transforms, and skips byte min/max statistics for spatial values.

Related issues

Related to #2411 and #1884.

Supersedes #2653, which was closed automatically by the stale bot. Existing review discussion remains available there.

@wirybeaver wirybeaver mentioned this pull request Jul 31, 2026
@brgr-s

brgr-s commented Jul 31, 2026

Copy link
Copy Markdown

In case you are interested, PR #2019 (CLOSED as stale) also has code related to geo types.

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few details around the conversion of types, but this is looking good to me!

Comment thread crates/iceberg/src/arrow/schema.rs
Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/arrow/schema.rs
Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/arrow/schema.rs
Comment thread crates/iceberg/src/spec/datatypes.rs Outdated

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not qualified to approve this from the icberg-rust end of things, but the geography type conversion seems solid (I suggested some optional improvements to errors inline). Thank you!

Happy to review any follow-ups on the statistics/pruning end of things if you are interested (or to attempt them if you aren't!).

I kept arrow-rs WkbType rather than introducing an Iceberg-specific copy because parquet 58.4 consumes its own WkbType; replacing only the Iceberg Arrow type would not fix the pre-59.1 Geography behavior and could make Parquet logical-type writing incompatible.

I think this is fine, although anybody who wants to write Geography will have to write invalid metadata into Iceberg (and will receive invalid metadata that will be rejected when reading using the arrow reader).

The workaround for this is to rewrite the metadata just for the Parquet reader, but I get how it's not worth adding that here since it will automatically resolve when arrow-rs is bumped. Our workaround for the write side is here:

https://github.com/apache/sedona-db/blob/ad83ab697b43998a4546359257015df71e210f18/rust/sedona-geoparquet/src/writer.rs#L681-L718

Can this be documented somehow?

Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/spec/datatypes.rs Outdated
Comment thread crates/iceberg/src/spec/datatypes.rs
Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
@wirybeaver

Copy link
Copy Markdown
Author

@paleolimbot Thanks for calling this out. I documented the arrow-rs 58.x Geography metadata limitation in 9a5d028 on the public Arrow schema conversion APIs. The docs now explain both directions: standards-compliant GeoArrow edges metadata may be interpreted as Geometry when importing, while exported Geography metadata uses the legacy algorithm key for parquet-rs 58.x compatibility and may be rejected or misinterpreted by standards-compliant Arrow readers. The note also links to apache/arrow-rs#10065, where this is fixed for 59.1.0+.

@paleolimbot

Copy link
Copy Markdown
Member

Great!

Can this be unmarked as draft? (i.e., is it ready for review from an iceberg committer?)

@wirybeaver
wirybeaver marked this pull request as ready for review August 6, 2026 01:50
@wirybeaver
wirybeaver force-pushed the support-geometry-geography-types branch from 9a5d028 to 3ae7041 Compare August 6, 2026 02:24
@paleolimbot

Copy link
Copy Markdown
Member

It seems like there's a merge conflict here. When that's fixed and CI is clean I'm happy to go fishing for iceberg-rust committers for review since this is a huge feature for us that will unblock a lot of things!

@wirybeaver
wirybeaver force-pushed the support-geometry-geography-types branch from 3ae7041 to bb2e601 Compare August 9, 2026 01:42
@Kurtiscwright

Copy link
Copy Markdown
Contributor

I kept arrow-rs WkbType rather than introducing an Iceberg-specific copy because parquet 58.4 consumes its own WkbType; replacing only the Iceberg Arrow type would not fix the pre-59.1 Geography behavior and could make Parquet logical-type writing incompatible.

@paleolimbot @wirybeaver I am have a very high level understanding of the Geo data type details, but this comment in paleolimbot's review confuses me. Does this mean that as this PR currently stands if a Java Iceberg reader attempts to read a Geo type data file created by this Rust library the Reader will break?

Is the current implementation inter-mixable with Iceberg Reader & Writer implementations from the Java & Golang communities?

@paleolimbot

Copy link
Copy Markdown
Member

Does this mean that as this PR currently stands if a Java Iceberg reader attempts to read a Geo type data file created by this Rust library the Reader will break?

Is the current implementation inter-mixable with Iceberg Reader & Writer implementations from the Java & Golang communities?

The reader will not break; however, until parquet is updated to 59.1.0, the conversion to and from Arrow types will have some errors. You can see which errors in the PR that fixed them ( apache/arrow-rs#10065 )...some of the cases are common, unfortunately. After the update to 59.1.0, these conversion to and from Arrow types will be the same as in golang and C++ (I don't believe Java converts to and from Arrow types, so there's nothing to compare to there).

We can inline that fix here or we can merge as is and get started on the rest of the geospatial support with a disclaimer. I don't mind which one (I'm happy to inline the fix as a PR into this one if that's helpful).

@CTTY

CTTY commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

DataFusion 55.0 is about to be released pretty soon (voting thread). I think we should just wait for datafusion 55.0 and arrow upgrade

@paleolimbot

Copy link
Copy Markdown
Member

Just linking #2958, as that should have the requisite arrow-rs version.

@dannycjones

Copy link
Copy Markdown
Contributor

I'd like to see this PR get some more attention and ultimately have support for the Geo types in iceberg-rust. Thank you for working on this, and for everyone who have provided reviews so far! With that said, the PR looks very large at the moment - can we find good ways to break it down and incrementally merge?

Variant so far has had success splitting into these streams: add ability to recognize the Variant type in tables and gracefully reject it / work around it (#2188), add the simpler unshredded read path for Variant (#2880), following up with shredded read and then writes.

@EwoutH shared some information previously which might be useful for breaking this down. #1884 (comment)

I'd like to take a look at this PR soon, but I think a good first PR to get merged in would be identifying the type and gracefully rejecting. In the meantime, after we cut 0.11.x it should allow #2958 to be merged soon after.

@paleolimbot

Copy link
Copy Markdown
Member

can we find good ways to break it down and incrementally merge

Given that this requires some domain expertise to review (e.g., from the spatial side), I'd prefer to have this as a unit so that I can keep track of spatial correctness.

@wirybeaver

Copy link
Copy Markdown
Author

#2598 get merged. I am working on the fix

@wirybeaver
wirybeaver force-pushed the support-geometry-geography-types branch from bb2e601 to c1d5762 Compare September 3, 2026 23:06
@wirybeaver
wirybeaver force-pushed the support-geometry-geography-types branch from 3f3a885 to 5951359 Compare September 4, 2026 16:04

@dannycjones dannycjones left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again work working on this, @wirybeaver! I've taken a look, although I apologize if any comments don't make sense - I'm new to geospatial types.

I don't see any read tests - is that left intentionally out of scope?

Comment on lines +2584 to +2585
assert!(data_file.lower_bounds().is_empty());
assert!(data_file.upper_bounds().is_empty());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you include an assertion message about why the bounds are empty? Is it simply because the field is optional, and this is left as a follow-up?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see its a follow-up, a code comment to confirm that would be good. #2933 (comment)

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs
Comment on lines +105 to +113
fn edge_interpolation_algorithm_to_wkb_edges(algorithm: EdgeInterpolationAlgorithm) -> WkbEdges {
match algorithm {
EdgeInterpolationAlgorithm::Spherical => WkbEdges::Spherical,
EdgeInterpolationAlgorithm::Vincenty => WkbEdges::Vincenty,
EdgeInterpolationAlgorithm::Thomas => WkbEdges::Thomas,
EdgeInterpolationAlgorithm::Andoyer => WkbEdges::Andoyer,
EdgeInterpolationAlgorithm::Karney => WkbEdges::Karney,
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not impl From<EdgeInterpolationAlgorithm> for WkbEdges? That way we get idiomatic/easy translation from the iceberg-rust type into the Parquet type (and the same for any future file format equivalent).

Same in reverse: impl From<WkbEdges> for EdgeInterpolationAlgorithm.

Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/arrow/schema.rs
Comment on lines +593 to +596
PrimitiveType::Geometry(geometry) => match geometry.crs() {
Some(crs) => write!(f, "geometry({crs})"),
None => write!(f, "geometry"),
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a variant in the spec without CRS provided. Should we write the default?

https://iceberg.apache.org/spec/#schemas

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know at least Spark rejects plain GEOMETRY but I don't know the relationship to iceberg.

Comment on lines +537 to +543
(
PrimitiveType::Geometry(_) | PrimitiveType::Geography(_),
JsonValue::String(_),
) => Err(Error::new(
ErrorKind::DataInvalid,
"Geometry and geography defaults must be null",
)),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong. While we may not allow defaults, there is a valid deserialization from JSON in the spec.

We need to add the check elsewhere in the code to disallow defaults.

Comment on lines +494 to +496
wkb_edges_to_edge_interpolation_algorithm(
wkb_type.metadata().algorithm.unwrap_or_default(),
),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this is the Parquet default, I'd rather we explicitly default for Iceberg.

Suggested change
wkb_edges_to_edge_interpolation_algorithm(
wkb_type.metadata().algorithm.unwrap_or_default(),
),
wkb_edges_to_edge_interpolation_algorithm(
wkb_type.metadata().algorithm.unwrap_or(WkbEdges::Spherical),
),

for i in 0..fields.len() {
let field = &fields[i];
let field_type = &field_results[i];
let field_type = self.apply_field_extension_type(field, &field_results[i])?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sorry, this comment isn't super actionable)

I need to better understand Variant's approach here. It appears to attach the field extension type earlier (I think because of field ID shenanigans), and I'm wondering if we should align or not. If we choose not to align, I think a comment is necessary on why they are separate.

Comment on lines +724 to +728
Type::Variant(_) => {
// A variant column's storage is a struct; tag the field with the canonical
// `arrow.parquet.variant` extension type so consumers read it as a Variant, not a struct.
arrow_field = arrow_field.with_extension_type(VariantExtensionType);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should update this to be try_with_extension_type for consistency (or update geospatial types to use with_extension_type if justified).

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a look from the spatial end...I think the translations for None CRSes aren't quite correct (this was one of the errors that was fixed by the upstream parquet-geospatial change). Thank you!

Comment thread crates/iceberg/src/arrow/schema.rs
Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs
Comment thread crates/iceberg/src/arrow/schema.rs Outdated
Comment thread crates/iceberg/src/arrow/schema.rs
Comment thread crates/iceberg/src/arrow/schema.rs
Co-authored-by: Dewey Dunnington <10995762+paleolimbot@users.noreply.github.com>
@wirybeaver

Copy link
Copy Markdown
Author

Add @paleolimbot as the co-author for the substantial review. Will check other folks review later on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants