This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git
The following commit(s) were added to refs/heads/main by this push:
new d9d1eded0 feat(table): Explicitly prohibit `GEOMETRY`/`GEOGRAPHY` ->
`BINARY` type promotion (#2221)
d9d1eded0 is described below
commit d9d1eded06a6426ed7f84c773d858590cdb37889
Author: Colton Loftus <[email protected]>
AuthorDate: Wed Oct 21 13:26:07 2026 -0400
feat(table): Explicitly prohibit `GEOMETRY`/`GEOGRAPHY` -> `BINARY` type
promotion (#2221)
* Explicitly align on geospatial type binary promotion behavior
* Respond to feedback
---
table/arrow_utils_test.go | 10 +++++-----
types.go | 4 ++++
types_test.go | 19 +++++++++++++++++++
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/table/arrow_utils_test.go b/table/arrow_utils_test.go
index 7b34a366b..7d94abd1d 100644
--- a/table/arrow_utils_test.go
+++ b/table/arrow_utils_test.go
@@ -3496,11 +3496,11 @@ func TestGeoTypeParquetRoundTrip(t *testing.T) {
// TestGeoParquetReadWithoutStoredSchema reads a GEOMETRY file that has no
// stored ARROW:schema, as Java/Spark writers produce. geoarrow-go maps the
// Parquet GEOMETRY logical type to geoarrow.wkb on read, so the file projects
-// onto a matching geometry column. A binary table column currently rejects it,
-// both on read and in the FileToDataFile (AddFiles) schema check. Whether
-// geometry should project onto a binary column is still an open decision
-// (https://github.com/apache/iceberg-go/issues/2193); flip the binary cases if
-// that promotion is allowed.
+// onto a matching geometry column. A binary table column rejects it, both on
+// read and in the FileToDataFile (AddFiles) schema check: geo types are
+// deliberately not promotable to or from binary (see iceberg.PromoteType and
+// https://github.com/apache/iceberg-go/issues/2193), and the binary subtests
+// assert that rejection.
func TestGeoParquetReadWithoutStoredSchema(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
diff --git a/types.go b/types.go
index 7ff35fa38..7407c1dba 100644
--- a/types.go
+++ b/types.go
@@ -1173,6 +1173,10 @@ func PromoteType(fileType, readType Type) (Type, error) {
if _, ok := readType.(BinaryType); ok {
return readType, nil
}
+ // BinaryType never promotes to or from GeometryType/GeographyType: the
spec
+ // lists no promotions for geo types, and plain binary isn't guaranteed
to
+ // hold valid WKB. Geo types reach the Equals check in default, so a
CRS or
+ // edge-algorithm change errors as well.
case BinaryType:
if _, ok := readType.(StringType); ok {
return readType, nil
diff --git a/types_test.go b/types_test.go
index c9ea9d47f..eb752cfb2 100644
--- a/types_test.go
+++ b/types_test.go
@@ -1103,6 +1103,15 @@ func TestNestedFieldEqualsWithNonComparableDefaults(t
*testing.T) {
}
func TestPromoteType(t *testing.T) {
+ geom4326, err := iceberg.GeometryTypeOf("srid:4326")
+ require.NoError(t, err)
+ geom3857, err := iceberg.GeometryTypeOf("srid:3857")
+ require.NoError(t, err)
+ geog, err := iceberg.GeographyTypeOf("srid:4326", "spherical")
+ require.NoError(t, err)
+ geogKarney, err := iceberg.GeographyTypeOf("srid:4326", "karney")
+ require.NoError(t, err)
+
tests := []struct {
name string
fileType iceberg.Type
@@ -1124,6 +1133,16 @@ func TestPromoteType(t *testing.T) {
{"decimal increase scale", iceberg.DecimalTypeOf(9, 2),
iceberg.DecimalTypeOf(18, 4), nil, true},
{"decimal decrease scale", iceberg.DecimalTypeOf(9, 4),
iceberg.DecimalTypeOf(18, 2), nil, true},
+ // Geo types never promote to or from binary; only identical
types pass.
+ {"geometry same", geom4326, geom4326, geom4326, false},
+ {"geography same", geog, geog, geog, false},
+ {"geometry to binary", geom4326, iceberg.PrimitiveTypes.Binary,
nil, true},
+ {"binary to geometry", iceberg.PrimitiveTypes.Binary, geom4326,
nil, true},
+ {"geography to binary", geog, iceberg.PrimitiveTypes.Binary,
nil, true},
+ {"binary to geography", iceberg.PrimitiveTypes.Binary, geog,
nil, true},
+ {"geometry crs mismatch", geom4326, geom3857, nil, true},
+ {"geography algorithm mismatch", geog, geogKarney, nil, true},
+
{"disallowed int to string", iceberg.PrimitiveTypes.Int32,
iceberg.PrimitiveTypes.String, nil, true},
{"disallowed fixed[8] to uuid", iceberg.FixedTypeOf(8),
iceberg.PrimitiveTypes.UUID, nil, true},
}