@@ -852,6 +852,25 @@ Result<::avro::NodePtr> CreateArrayNodeWithFieldIds(const ::avro::NodePtr& origi
852852 ICEBERG_ASSIGN_OR_RAISE (auto new_element_node,
853853 MakeAvroNodeWithFieldIds (original_node->leafAt (0 ), field));
854854 new_array_node->addLeaf (new_element_node);
855+
856+ // Check and add custom attributes
857+ if (original_node->customAttributes () > 0 ) {
858+ ::avro::CustomAttributes merged_attributes;
859+ const auto & original_attrs = original_node->customAttributesAt (0 );
860+ const auto & existing_attrs = original_attrs.attributes ();
861+ for (const auto & attr_pair : existing_attrs) {
862+ // Skip element-id as we might set it differently
863+ if (attr_pair.first != kElementIdProp ) {
864+ merged_attributes.addAttribute (attr_pair.first , attr_pair.second ,
865+ /* addQuote=*/ false );
866+ }
867+ }
868+ // Add merged attributes if we found any
869+ if (merged_attributes.attributes ().size () > 0 ) {
870+ new_array_node->addCustomAttributesForField (merged_attributes);
871+ }
872+ }
873+
855874 return new_array_node;
856875 }
857876
@@ -871,12 +890,29 @@ Result<::avro::NodePtr> CreateArrayNodeWithFieldIds(const ::avro::NodePtr& origi
871890 MakeAvroNodeWithFieldIds (original_node->leafAt (0 ), element_field));
872891 new_array_node->addLeaf (new_element_node);
873892
874- // Add element field ID as custom attribute
875- ::avro::CustomAttributes element_attributes;
876- element_attributes.addAttribute (std::string (kElementIdProp ),
877- std::to_string (*element_field.field_id ),
878- /* addQuote=*/ false );
879- new_array_node->addCustomAttributesForField (element_attributes);
893+ // Create merged custom attributes with element field ID
894+ ::avro::CustomAttributes merged_attributes;
895+
896+ // First add our element field ID (highest priority)
897+ merged_attributes.addAttribute (std::string (kElementIdProp ),
898+ std::to_string (*element_field.field_id ),
899+ /* addQuote=*/ false );
900+
901+ // Then merge any custom attributes from original node (except element-id)
902+ if (original_node->customAttributes () > 0 ) {
903+ const auto & original_attrs = original_node->customAttributesAt (0 );
904+ const auto & existing_attrs = original_attrs.attributes ();
905+ for (const auto & attr_pair : existing_attrs) {
906+ // Skip element-id as we've already set it above
907+ if (attr_pair.first != kElementIdProp ) {
908+ merged_attributes.addAttribute (attr_pair.first , attr_pair.second ,
909+ /* addQuote=*/ false );
910+ }
911+ }
912+ }
913+
914+ // Add all attributes at once
915+ new_array_node->addCustomAttributesForField (merged_attributes);
880916
881917 return new_array_node;
882918}
@@ -917,29 +953,47 @@ Result<::avro::NodePtr> CreateMapNodeWithFieldIds(const ::avro::NodePtr& origina
917953 new_map_node->addLeaf (new_key_node);
918954 new_map_node->addLeaf (new_value_node);
919955
920- // Preserve existing custom attributes from the original node and add field ID
921- // attributes Copy existing attributes from the original node (if any)
922- if (original_node->customAttributes () > 0 ) {
923- const auto & original_attrs = original_node->customAttributesAt (0 );
924- const auto & existing_attrs = original_attrs.attributes ();
925- for (const auto & attr_pair : existing_attrs) {
926- // Copy each existing attribute to preserve original metadata
927- ::avro::CustomAttributes attributes;
928- attributes.addAttribute (attr_pair.first , attr_pair.second , /* addQuote=*/ false );
929- new_map_node->addCustomAttributesForField (attributes);
930- }
931- }
932-
956+ // Create key and value attributes
933957 ::avro::CustomAttributes key_attributes;
958+ ::avro::CustomAttributes value_attributes;
959+
960+ // Add required field IDs
934961 key_attributes.addAttribute (std::string (kKeyIdProp ),
935962 std::to_string (*key_mapped_field.field_id ),
936963 /* addQuote=*/ false );
937- new_map_node->addCustomAttributesForField (key_attributes);
938-
939- ::avro::CustomAttributes value_attributes;
940964 value_attributes.addAttribute (std::string (kValueIdProp ),
941965 std::to_string (*value_mapped_field.field_id ),
942966 /* addQuote=*/ false );
967+
968+ // Merge custom attributes from original node if they exist
969+ if (original_node->customAttributes () > 0 ) {
970+ // Merge attributes for key (index 0)
971+ const auto & original_key_attrs = original_node->customAttributesAt (0 );
972+ const auto & existing_key_attrs = original_key_attrs.attributes ();
973+ for (const auto & attr_pair : existing_key_attrs) {
974+ // Skip if it's the key ID property we're already setting
975+ if (attr_pair.first != kKeyIdProp ) {
976+ key_attributes.addAttribute (attr_pair.first , attr_pair.second ,
977+ /* addQuote=*/ false );
978+ }
979+ }
980+
981+ // Merge attributes for value (index 1)
982+ if (original_node->customAttributes () > 1 ) {
983+ const auto & original_value_attrs = original_node->customAttributesAt (1 );
984+ const auto & existing_value_attrs = original_value_attrs.attributes ();
985+ for (const auto & attr_pair : existing_value_attrs) {
986+ // Skip if it's the value ID property we're already setting
987+ if (attr_pair.first != kValueIdProp ) {
988+ value_attributes.addAttribute (attr_pair.first , attr_pair.second ,
989+ /* addQuote=*/ false );
990+ }
991+ }
992+ }
993+ }
994+
995+ // Add the merged attributes to the new map node
996+ new_map_node->addCustomAttributesForField (key_attributes);
943997 new_map_node->addCustomAttributesForField (value_attributes);
944998
945999 return new_map_node;
0 commit comments