nazq opened a new pull request, #2563:
URL: https://github.com/apache/iceberg-rust/pull/2563

   ## Which issue does this PR close?
   
   - Closes #2562.
   
   ## What changes are included in this PR?
   
   Adds `rename_column` to `UpdateSchemaAction`, completing the 
add/delete/rename triad for non-incompatible schema evolution in 
`transaction::update_schema`.
   
   ### Public API
   
   ```rust
   let tx = Transaction::new(&table);
   let action = tx.update_schema()
       .add_column(AddColumn::optional("new_col", 
Type::Primitive(PrimitiveType::Int)))
       .rename_column("old_name", "new_name")
       .rename_column("person.name", "fullname")  // nested supported
       .delete_column("dead_col");
   let tx = action.apply(tx).unwrap();
   let table = tx.commit(&catalog).await.unwrap();
   ```
   
   `rename_column(path_from, new_name)` mirrors the existing `add_column` / 
`delete_column` builder shape. Field IDs are preserved across rename — only the 
leaf name changes.
   
   ### Implementation
   
   A new `renames: Vec<(String, String)>` accumulator on `UpdateSchemaAction`, 
plus a new step in `commit()` between deletes and additions:
   
   - **After deletes** so a rename can re-use a name being deleted in the same 
action.
   - **Before additions** so an addition can re-use a name being renamed away.
   
   The renames are resolved to a `HashMap<i32, String>` keyed by field ID, then 
threaded through `rebuild_fields` / `rebuild_field` — same recursive walk that 
handles deletes and nested additions. Each rebuild call site that previously 
copied `field.name.clone()` now looks up the rename map first and falls back to 
the original name. Identifier-field handling falls out for free because Rust 
keys `identifier_field_ids` by ID, not name — the existing 
`with_identifier_field_ids(base_schema.identifier_field_ids())` step propagates 
the set unchanged.
   
   ### Semantics
   
   Modeled on `pyiceberg.table.update.schema.UpdateSchema.rename_column`:
   
   - `path_from` must exist in the current schema → otherwise 
`PreconditionFailed`.
   - A field cannot be both renamed and deleted in the same action → 
`PreconditionFailed` (intent is ambiguous; matches PyIceberg).
   - `new_name` cannot contain `SCHEMA_NAME_DELIMITER` → `PreconditionFailed` 
(the unqualified-name requirement; preventing it from silently looking like a 
move-across-structs).
   - `new_name` cannot collide with a sibling that is not itself being deleted 
or renamed away → `PreconditionFailed`.
   - Same field renamed twice → last rename wins (matches PyIceberg's "stack on 
prior update" behavior).
   
   ### Scope
   
   `rename_column` only. PyIceberg's `UpdateSchema` has other ops 
(`update_column`, `make_column_required`, `move_*`, `set_identifier_fields`) — 
those are out of scope here and would be follow-up PRs if there's interest.
   
   ## Are these changes tested?
   
   Yes — 10 new unit tests in `transaction::update_schema::tests`, matching the 
style and depth of the existing `test_*_add_column*` / `test_*_delete_column*` 
tests:
   
   | Test | What it covers |
   |---|---|
   | `test_rename_column` | Simple root-level rename, verifies field ID 
preserved |
   | `test_rename_nested_column` | Nested rename (`person.name` → 
`person.fullname`), preserves sibling fields |
   | `test_rename_missing_column_fails` | Missing source field → 
`PreconditionFailed` |
   | `test_rename_and_delete_same_column_fails` | Rename + delete on same 
column → `PreconditionFailed` |
   | `test_rename_to_existing_sibling_fails` | Collision with a non-deleted, 
non-renamed sibling → `PreconditionFailed` |
   | `test_rename_path_with_dot_in_new_name_fails` | Rejects qualified new name 
|
   | `test_rename_identifier_field_preserves_identifier_ids` | Verifies 
`identifier_field_ids` is preserved across rename of an identifier field |
   | `test_rename_frees_name_for_addition` | Composition test: rename + add 
re-uses the old name |
   | `test_rename_same_column_twice_last_wins` | Idempotency / "last wins" 
semantics |
   | `test_rename_self_is_noop` | Rename to current name produces unchanged 
schema |
   
   All 18 existing `transaction::update_schema` tests still pass (no 
regressions). Full `iceberg` lib suite: 1306/1306 passing. Clippy + rustfmt 
clean.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to