Skip to content

check_name_does_not_collide_with_schema incorrectly rejects Void transform partitions whose names collide with schema columns #2567

@TwinklerG

Description

@TwinklerG

Apache Iceberg Rust version

0.6.0 (latest version)

Describe the bug

When a partition field's transform is changed from Identity to Void (to effectively drop the field in v1 tables), re-binding the unbound partition spec to the schema fails because
check_name_does_not_collide_with_schema treats Void the same as other non-Identity transforms and rejects the name collision.

However, Void transforms always produce null results, so they pose no semantic conflict with schema columns — just like Identity transforms sourced from the same column. The check should allow Void
transforms under the same condition as Identity.

To Reproduce

use iceberg::spec::{                                                                                                                                                                                     
    NestedField, PartitionSpec, Schema, Transform, Type, UnboundPartitionField, PrimitiveType,                                                                                                           
};                                                                                                                                                                                                       
                                                                                                                                                                                                         
let schema = Schema::builder()                                                                                                                                                                           
    .with_fields(vec![                                                                                                                                                                                   
        NestedField::required(1, "id", Type::Primitive(PrimitiveType::Int)).into(),                                                                                                                      
    ])                                                                                                                                                                                                   
    .build()                                                                                                                                                                                             
    .unwrap();                                                                                                                                                                                           
                                                                                                                                                                                                         
// Simulate a previously valid identity partition whose transform was changed to Void                                                                                                                    
let unbound = UnboundPartitionField {                                                                                                                                                                    
    source_id: 1,                                                                                                                                                                                        
    field_id: Some(1000),                                                                                                                                                                                
    name: "id".to_string(), // same name as schema column                                                                                                                                                
    transform: Transform::Void,                                                                                                                                                                          
};                                                                                                                                                                                                       
                                                                                                                                                                                                         
// Binding back fails                                                                                                                                                                                    
let err = PartitionSpec::builder(schema)                                                                                                                                                                 
    .add_unbound_field(unbound)                                                                                                                                                                          
    .unwrap_err();                                                                                                                                                                                       
                                                                                                                                                                                                         
assert!(err.message().contains("conflicts with schema")); // currently passes (fails as expected)                                                                                                        
// But it should succeed — Void transform produces only null, no semantic conflict                                                                                                                       

Expected behavior

check_name_does_not_collide_with_schema should allow Void transforms when the partition name collides with a schema column and the source_id matches, treating Void the same as Identity for this check.

Willingness to contribute

I can contribute a fix for this bug independently

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions