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 059d0b7ba fix(table): rename void field before reusing its name (#2473)
059d0b7ba is described below

commit 059d0b7ba8cd050c53a83eb75bde17ae655a41f1
Author: Minh Vu <[email protected]>
AuthorDate: Mon Nov 9 20:45:57 2026 +0100

    fix(table): rename void field before reusing its name (#2473)
    
    fix(table): preserve void tombstones when renaming fields
---
 table/update_spec.go      | 22 ++++++++++++++--------
 table/update_spec_test.go | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/table/update_spec.go b/table/update_spec.go
index 25976e2cc..adbb17346 100644
--- a/table/update_spec.go
+++ b/table/update_spec.go
@@ -432,14 +432,6 @@ func (us *UpdateSpec) historicalPartitionFields(key 
transformKey) []iceberg.Part
 
 func (us *UpdateSpec) renameField(name string, newName string) updateSpecOp {
        return func() error {
-               existingField, exists := us.nameToField[newName]
-               _, isVoidTransform := 
existingField.Transform.(iceberg.VoidTransform)
-               if exists && isVoidTransform {
-                       return us.renameField(
-                               name,
-                               fmt.Sprintf("%s_%d", name, 
existingField.FieldID),
-                       )()
-               }
                if _, added := us.nameToAddedField[name]; added {
                        return errors.New("cannot rename recently added 
partitions")
                }
@@ -451,6 +443,20 @@ func (us *UpdateSpec) renameField(name string, newName 
string) updateSpecOp {
                if _, deleted := us.deletes[field.FieldID]; deleted {
                        return fmt.Errorf("cannot delete and rename partition 
field: %s", name)
                }
+
+               existingField, exists := us.nameToField[newName]
+               _, isVoidTransform := 
existingField.Transform.(iceberg.VoidTransform)
+               if exists && isVoidTransform {
+                       // Move the old v1 tombstone out of the way before 
assigning its
+                       // name to the field being renamed.
+                       if err := us.renameField(
+                               existingField.Name,
+                               fmt.Sprintf("%s_%d", existingField.Name, 
existingField.FieldID),
+                       )(); err != nil {
+                               return err
+                       }
+               }
+
                us.renames[name] = newName
 
                return nil
diff --git a/table/update_spec_test.go b/table/update_spec_test.go
index 8eb4738b3..c6d7727e9 100644
--- a/table/update_spec_test.go
+++ b/table/update_spec_test.go
@@ -720,6 +720,39 @@ func TestUpdateSpecRenameField(t *testing.T) {
        })
 }
 
+func TestUpdateSpecRenameFieldIntoVoidTombstoneName(t *testing.T) {
+       spec := iceberg.NewPartitionSpec(
+               iceberg.PartitionField{
+                       SourceIDs: []int{1},
+                       FieldID:   iceberg.PartitionDataIDStart,
+                       Name:      "region",
+                       Transform: iceberg.IdentityTransform{},
+               },
+               iceberg.PartitionField{
+                       SourceIDs: []int{2},
+                       FieldID:   iceberg.PartitionDataIDStart + 1,
+                       Name:      "country",
+                       Transform: iceberg.VoidTransform{},
+               },
+       )
+       meta, err := table.NewMetadata(testSchema, &spec, 
table.UnsortedSortOrder, "",
+               iceberg.Properties{table.PropertyFormatVersion: "1"})
+       require.NoError(t, err)
+       tbl := table.New([]string{"v1_void_rename"}, meta, "", nil, nil)
+
+       update := table.NewUpdateSpec(tbl.NewTransaction(), 
false).RenameField("region", "country")
+       _, _, err = update.BuildUpdates()
+       require.NoError(t, err)
+
+       newSpec, err := update.Apply()
+       require.NoError(t, err)
+       require.Equal(t, 2, newSpec.NumFields())
+       assert.Equal(t, "country", newSpec.Field(0).Name)
+       assert.Equal(t, iceberg.IdentityTransform{}, newSpec.Field(0).Transform)
+       assert.Equal(t, "country_1001", newSpec.Field(1).Name)
+       assert.Equal(t, iceberg.VoidTransform{}, newSpec.Field(1).Transform)
+}
+
 func TestUpdateSpecRemoveField(t *testing.T) {
        var txn *table.Transaction
 

Reply via email to