@@ -230,7 +230,7 @@ mod tests {
230230 use arrow:: buffer:: { Buffer , NullBuffer } ;
231231 use arrow_schema:: { DataType , Field , FieldRef , Fields , Schema , SchemaRef } ;
232232 use delta_kernel:: engine:: arrow_conversion:: TryIntoKernel as _;
233- use delta_kernel:: schema:: MetadataValue ;
233+ use delta_kernel:: schema:: { ColumnMetadataKey , MetadataValue } ;
234234 use itertools:: Itertools ;
235235
236236 use super :: merge_schema:: { merge_arrow_schema, merge_delta_struct} ;
@@ -286,6 +286,71 @@ mod tests {
286286 assert_eq ! ( fields[ 0 ] . metadata( ) , & expected_meta) ;
287287 }
288288
289+ #[ test]
290+ fn test_merge_arrow_schema_preserves_table_field_metadata_when_batch_missing ( ) {
291+ let mut left_meta = HashMap :: new ( ) ;
292+ left_meta. insert (
293+ ColumnMetadataKey :: GenerationExpression . as_ref ( ) . to_string ( ) ,
294+ "id + value" . to_string ( ) ,
295+ ) ;
296+
297+ let left_schema = Arc :: new ( Schema :: new ( vec ! [
298+ Field :: new( "computed" , DataType :: Int32 , false ) . with_metadata( left_meta) ,
299+ ] ) ) ;
300+
301+ // Incoming batch/schema omits field metadata; table metadata must remain intact.
302+ let right_schema = Arc :: new ( Schema :: new ( vec ! [ Field :: new(
303+ "computed" ,
304+ DataType :: Int32 ,
305+ false ,
306+ ) ] ) ) ;
307+
308+ let merged = merge_arrow_schema ( left_schema, right_schema, true ) . unwrap ( ) ;
309+ let computed = merged. field_with_name ( "computed" ) . unwrap ( ) ;
310+ assert_eq ! (
311+ computed
312+ . metadata( )
313+ . get( ColumnMetadataKey :: GenerationExpression . as_ref( ) )
314+ . map( |v| v. as_str( ) ) ,
315+ Some ( "id + value" )
316+ ) ;
317+ }
318+
319+ #[ test]
320+ fn test_merge_arrow_schema_ignores_batch_generation_expression_conflicts ( ) {
321+ let mut left_meta = HashMap :: new ( ) ;
322+ left_meta. insert (
323+ ColumnMetadataKey :: GenerationExpression . as_ref ( ) . to_string ( ) ,
324+ "id + value" . to_string ( ) ,
325+ ) ;
326+
327+ let mut right_meta = HashMap :: new ( ) ;
328+ right_meta. insert (
329+ ColumnMetadataKey :: GenerationExpression . as_ref ( ) . to_string ( ) ,
330+ "id * 10" . to_string ( ) ,
331+ ) ;
332+
333+ let left_schema = Arc :: new ( Schema :: new ( vec ! [
334+ Field :: new( "computed" , DataType :: Int32 , false ) . with_metadata( left_meta) ,
335+ ] ) ) ;
336+
337+ // Batch metadata may include `delta.generationExpression`, but the table's
338+ // generation expression is authoritative and should not be overridden.
339+ let right_schema = Arc :: new ( Schema :: new ( vec ! [
340+ Field :: new( "computed" , DataType :: Int32 , false ) . with_metadata( right_meta) ,
341+ ] ) ) ;
342+
343+ let merged = merge_arrow_schema ( left_schema, right_schema, true ) . unwrap ( ) ;
344+ let computed = merged. field_with_name ( "computed" ) . unwrap ( ) ;
345+ assert_eq ! (
346+ computed
347+ . metadata( )
348+ . get( ColumnMetadataKey :: GenerationExpression . as_ref( ) )
349+ . map( |v| v. as_str( ) ) ,
350+ Some ( "id + value" )
351+ ) ;
352+ }
353+
289354 #[ test]
290355 fn test_merge_arrow_schema_with_nested ( ) {
291356 let left_schema = Arc :: new ( Schema :: new ( vec ! [ Field :: new(
0 commit comments