Add rename_column support to UpdateSchemaAction
Label: enhancement
Is your feature request related to a problem or challenge?
UpdateSchemaAction currently supports add_column and delete_column (PR #2120), but not rename_column. Schema evolution APIs in sibling implementations (PyIceberg, Java) all expose rename as a first-class operation, and downstream Rust users who need parity with those implementations have to fall back to:
The add_column / delete_column infrastructure already does almost everything rename needs (the rebuild-the-schema-tree pattern, the AddSchema + SetCurrentSchema emission, the CurrentSchemaIdMatch requirement). The gap is just the builder method, the validation, and threading the renames through the rebuild step.
Describe the solution you'd like
A new builder method on UpdateSchemaAction matching the existing add/delete shape:
let tx = Transaction::new(&table);
let action = tx.update_schema()
.rename_column("old_name", "new_name")
.rename_column("person.name", "fullname"); // nested supported
let tx = action.apply(tx).unwrap();
let table = tx.commit(&catalog).await.unwrap();
Semantics modeled on pyiceberg.table.update.schema.UpdateSchema.rename_column:
- Field ID is preserved. This is Iceberg's invariant — rename is a metadata-only operation on the name; the column ID stays stable so existing data files and snapshots remain valid.
path_from uses SCHEMA_NAME_DELIMITER (.) for nested fields. new_name is the unqualified leaf name; rename does not move a field between parent structs.
- Identifier fields handled transparently. Iceberg keys
identifier_field_ids by ID, not name, so the existing with_identifier_field_ids(base_schema.identifier_field_ids()) step in commit() already propagates them correctly across renames.
- Composes with add/delete in the same action. A rename frees the old name for re-use by an addition; the renamed field can take a name previously held by a sibling being deleted.
Validation rules (all PreconditionFailed):
path_from must exist in the current schema.
- A field cannot be both renamed and deleted in the same action — intent is ambiguous.
new_name cannot contain SCHEMA_NAME_DELIMITER — would otherwise silently look like a move-across-structs.
new_name cannot collide with a sibling that is not itself being deleted or renamed away.
- If the same field is renamed multiple times, the last rename wins (matches PyIceberg).
Scope
This issue covers only rename_column. PyIceberg's UpdateSchema exposes other operations not covered here:
update_column (type promotion / nullability / doc edits)
make_column_optional / make_column_required
move_first / move_before / move_after
set_identifier_fields
Those are out of scope and would be follow-up issues if there's interest.
Willingness to contribute
I can contribute to this feature independently. I have a working branch with the implementation + 10 new unit tests (matching the style and depth of the existing test_*_add_column* / test_*_delete_column* tests in transaction::update_schema::tests), and a PR ready to open once this issue is filed for reference.
Add
rename_columnsupport toUpdateSchemaActionLabel:
enhancementIs your feature request related to a problem or challenge?
UpdateSchemaActioncurrently supportsadd_columnanddelete_column(PR #2120), but notrename_column. Schema evolution APIs in sibling implementations (PyIceberg, Java) all expose rename as a first-class operation, and downstream Rust users who need parity with those implementations have to fall back to:The
add_column/delete_columninfrastructure already does almost everything rename needs (the rebuild-the-schema-tree pattern, theAddSchema+SetCurrentSchemaemission, theCurrentSchemaIdMatchrequirement). The gap is just the builder method, the validation, and threading the renames through the rebuild step.Describe the solution you'd like
A new builder method on
UpdateSchemaActionmatching the existing add/delete shape:Semantics modeled on
pyiceberg.table.update.schema.UpdateSchema.rename_column:path_fromusesSCHEMA_NAME_DELIMITER(.) for nested fields.new_nameis the unqualified leaf name; rename does not move a field between parent structs.identifier_field_idsby ID, not name, so the existingwith_identifier_field_ids(base_schema.identifier_field_ids())step incommit()already propagates them correctly across renames.Validation rules (all
PreconditionFailed):path_frommust exist in the current schema.new_namecannot containSCHEMA_NAME_DELIMITER— would otherwise silently look like a move-across-structs.new_namecannot collide with a sibling that is not itself being deleted or renamed away.Scope
This issue covers only
rename_column. PyIceberg'sUpdateSchemaexposes other operations not covered here:update_column(type promotion / nullability / doc edits)make_column_optional/make_column_requiredmove_first/move_before/move_afterset_identifier_fieldsThose are out of scope and would be follow-up issues if there's interest.
Willingness to contribute
I can contribute to this feature independently. I have a working branch with the implementation + 10 new unit tests (matching the style and depth of the existing
test_*_add_column*/test_*_delete_column*tests intransaction::update_schema::tests), and a PR ready to open once this issue is filed for reference.