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