@@ -55,6 +55,40 @@ func TestBufferingSinkNewFieldDedup(t *testing.T) {
5555 })
5656}
5757
58+ // TestSchemaEvolutionColumnNameNormalization verifies that when
59+ // case_sensitive_columns=false, new column names are normalised to lowercase
60+ // before being stored in the UnknownFieldError that drives AddColumn. Without
61+ // this, a message keyed "EMAIL" would add an uppercase column to an otherwise
62+ // lowercase schema, violating iceberg's recommended convention.
63+ func TestSchemaEvolutionColumnNameNormalization (t * testing.T ) {
64+ t .Run ("buffering sink normalises to lowercase" , func (t * testing.T ) {
65+ sink := newBufferingSink (nil , 0 , false )
66+ sink .OnNewField (icebergx.Path {}, "EMAIL" , "a@x.z" )
67+
68+ errs := sink .newFieldErrors ()
69+ require .Len (t , errs , 1 )
70+ assert .Equal (t , "email" , errs [0 ].FieldName ())
71+ })
72+
73+ t .Run ("parquet sink normalises to lowercase" , func (t * testing.T ) {
74+ sink := & parquetSink {caseSensitive : false }
75+ sink .OnNewField (icebergx.Path {}, "EMAIL" , "a@x.z" )
76+
77+ errs := sink .newFieldErrors ()
78+ require .Len (t , errs , 1 )
79+ assert .Equal (t , "email" , errs [0 ].FieldName ())
80+ })
81+
82+ t .Run ("case-sensitive mode preserves original capitalisation" , func (t * testing.T ) {
83+ sink := newBufferingSink (nil , 0 , true )
84+ sink .OnNewField (icebergx.Path {}, "EMAIL" , "a@x.z" )
85+
86+ errs := sink .newFieldErrors ()
87+ require .Len (t , errs , 1 )
88+ assert .Equal (t , "EMAIL" , errs [0 ].FieldName ())
89+ })
90+ }
91+
5892// TestParquetSinkNewFieldDedup mirrors TestBufferingSinkNewFieldDedup for the
5993// non-buffering parquet sink, which is used for unpartitioned writes.
6094func TestParquetSinkNewFieldDedup (t * testing.T ) {
0 commit comments