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},
        }

Reply via email to