This is an automated email from the ASF dual-hosted git repository.

markap14 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 047ad87a3b6 NIFI-15329 - Fix RenameRecordField to properly handle 
multiple records (#10629)
047ad87a3b6 is described below

commit 047ad87a3b6f4a58db6ec51a49159618d95505a9
Author: Pierre Villard <[email protected]>
AuthorDate: Thu Dec 11 15:35:06 2025 +0100

    NIFI-15329 - Fix RenameRecordField to properly handle multiple records 
(#10629)
---
 .gitignore                                         |  1 +
 .../nifi/serialization/record/MapRecord.java       | 39 ++++++++++++++++++++++
 .../processors/standard/RenameRecordField.java     |  5 +++
 .../input/complex-person.json                      | 13 +++++++-
 .../TestRenameRecordField/input/simple-person.json |  6 +++-
 .../output/testNestedPath.json                     | 11 ++++++
 .../testRecursivelyReferencingAllFields.json       | 11 ++++++
 .../testRecursivelyReferencingFieldName.json       | 11 ++++++
 .../output/testReferencingFieldName.json           |  4 +++
 .../output/testRenameArray.json                    | 11 ++++++
 .../output/testRenameFieldStaticValue.json         |  4 +++
 .../output/testRenameFieldUsingAttribute.json      |  4 +++
 .../output/testRenameMultipleFields.json           |  4 +++
 13 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index bc18e8dbb49..ff8a118e9a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 target
+bin
 .project
 .settings
 .classpath
diff --git 
a/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
 
b/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
index 37d787cf56e..794854f7cf7 100644
--- 
a/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
+++ 
b/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
@@ -50,6 +50,7 @@ public class MapRecord implements Record {
     private static final Logger logger = 
LoggerFactory.getLogger(MapRecord.class);
 
     private RecordSchema schema;
+    private boolean mutableSchema = false; // Track if schema is a private 
copy that can be safely modified
     private final Map<String, Object> values;
     private Optional<SerializedForm> serializedForm;
     private final boolean checkTypes;
@@ -525,6 +526,15 @@ public class MapRecord implements Record {
             throw new IllegalArgumentException("Could not rename [" + field + 
"] to [" + newName + "] because a field already exists with the name [" + 
newName + "]");
         }
 
+        // Create a defensive copy of the schema to avoid modifying a shared 
schema instance.
+        // Multiple records often share the same schema object for efficiency. 
If we modify
+        // the shared schema, subsequent records would fail to find the 
original field name.
+        // Only copy if we haven't already made a private copy.
+        if (!mutableSchema) {
+            this.schema = new SimpleRecordSchema(new 
ArrayList<>(schema.getFields()));
+            this.mutableSchema = true;
+        }
+
         final String currentName = resolvedField.get().getFieldName();
         final boolean renamed = schema.renameField(currentName, newName);
         if (!renamed) {
@@ -545,7 +555,36 @@ public class MapRecord implements Record {
             if (schemaField.getDataType().getFieldType() == 
RecordFieldType.CHOICE) {
                 schemaFields.add(schemaField);
             } else if (fieldValue instanceof final Record childRecord) {
+                childRecord.regenerateSchema();
                 schemaFields.add(new RecordField(schemaField.getFieldName(), 
RecordFieldType.RECORD.getRecordDataType(childRecord.getSchema()), 
schemaField.isNullable()));
+            } else if (schemaField.getDataType().getFieldType() == 
RecordFieldType.ARRAY && fieldValue instanceof Object[]) {
+                // Handle arrays of records - regenerate schema based on 
actual element schemas
+                final ArrayDataType arrayType = (ArrayDataType) 
schemaField.getDataType();
+                final DataType elementType = arrayType.getElementType();
+                if (elementType.getFieldType() == RecordFieldType.RECORD) {
+                    final Object[] array = (Object[]) fieldValue;
+                    RecordSchema mergedElementSchema = null;
+                    for (final Object element : array) {
+                        if (element instanceof Record) {
+                            final Record elementRecord = (Record) element;
+                            elementRecord.regenerateSchema();
+                            if (mergedElementSchema == null) {
+                                mergedElementSchema = 
elementRecord.getSchema();
+                            } else {
+                                mergedElementSchema = 
DataTypeUtils.merge(mergedElementSchema, elementRecord.getSchema());
+                            }
+                        }
+                    }
+                    if (mergedElementSchema != null) {
+                        final DataType newElementType = 
RecordFieldType.RECORD.getRecordDataType(mergedElementSchema);
+                        final DataType newArrayType = 
RecordFieldType.ARRAY.getArrayDataType(newElementType);
+                        schemaFields.add(new 
RecordField(schemaField.getFieldName(), newArrayType, 
schemaField.isNullable()));
+                    } else {
+                        schemaFields.add(schemaField);
+                    }
+                } else {
+                    schemaFields.add(schemaField);
+                }
             } else {
                 schemaFields.add(schemaField);
             }
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
index 91d2c6a1686..baae7928ee1 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
@@ -206,6 +206,11 @@ public class RenameRecordField extends 
AbstractRecordProcessor {
             }
         }
 
+        // After renaming fields (especially in nested records), we need to 
update the
+        // top-level record's schema to reflect the schema changes in nested 
records.
+        // This ensures the writer uses the correct schema with renamed fields.
+        record.regenerateSchema();
+
         return record;
     }
 }
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
index 5de7972913b..77b15c641ba 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
@@ -9,4 +9,15 @@
     "state" : "MS",
     "zip" : "90210"
   } ]
-} ]
\ No newline at end of file
+}, {
+  "name" : "Jane Smith",
+  "age" : 25,
+  "application" : "Apache Kafka",
+  "addresses" : [ {
+    "name" : "Work",
+    "street" : "1234 Office Blvd",
+    "city" : "Tech Town",
+    "state" : "CA",
+    "zip" : "94105"
+  } ]
+} ]
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
index 9254388546c..42ac9f743a4 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
@@ -2,4 +2,8 @@
   "name" : "John Doe",
   "age" : 30,
   "application" : "Apache NiFi"
-} ]
\ No newline at end of file
+}, {
+  "name" : "Jane Smith",
+  "age" : 25,
+  "application" : "Apache Kafka"
+} ]
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
index c1ef08b79d8..72153539355 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
@@ -9,4 +9,15 @@
     "state" : "MS",
     "zip" : "90210"
   } ]
+}, {
+  "name" : "Jane Smith",
+  "age" : 25,
+  "application" : "Apache Kafka",
+  "addresses" : [ {
+    "name" : "Work",
+    "streetAddress" : "1234 Office Blvd",
+    "city" : "Tech Town",
+    "state" : "CA",
+    "zip" : "94105"
+  } ]
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
index 72df009e4c0..26d7a394657 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
@@ -9,4 +9,15 @@
     "STATE" : "MS",
     "ZIP" : "90210"
   } ]
+}, {
+  "NAME" : "Jane Smith",
+  "AGE" : 25,
+  "APPLICATION" : "Apache Kafka",
+  "ADDRESSES" : [ {
+    "NAME" : "Work",
+    "STREET" : "1234 Office Blvd",
+    "CITY" : "Tech Town",
+    "STATE" : "CA",
+    "ZIP" : "94105"
+  } ]
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
index 40f3530c61a..273b7020663 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
@@ -9,4 +9,15 @@
     "state" : "MS",
     "zip" : "90210"
   } ]
+}, {
+  "NAME" : "Jane Smith",
+  "age" : 25,
+  "application" : "Apache Kafka",
+  "addresses" : [ {
+    "NAME" : "Work",
+    "street" : "1234 Office Blvd",
+    "city" : "Tech Town",
+    "state" : "CA",
+    "zip" : "94105"
+  } ]
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
index a72fc8b3604..ef041653654 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
@@ -2,4 +2,8 @@
   "UPDATED_name" : "John Doe",
   "UPDATED_age" : 30,
   "UPDATED_application" : "Apache NiFi"
+}, {
+  "UPDATED_name" : "Jane Smith",
+  "UPDATED_age" : 25,
+  "UPDATED_application" : "Apache Kafka"
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
index 3f11cf24d29..7174e6d7786 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
@@ -9,4 +9,15 @@
     "state" : "MS",
     "zip" : "90210"
   } ]
+}, {
+  "name" : "Jane Smith",
+  "age" : 25,
+  "application" : "Apache Kafka",
+  "addrs" : [ {
+    "name" : "Work",
+    "street" : "1234 Office Blvd",
+    "city" : "Tech Town",
+    "state" : "CA",
+    "zip" : "94105"
+  } ]
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
index 58aec362dab..a9875696066 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
@@ -2,4 +2,8 @@
   "name" : "John Doe",
   "age" : 30,
   "favoriteApplication" : "Apache NiFi"
+}, {
+  "name" : "Jane Smith",
+  "age" : 25,
+  "favoriteApplication" : "Apache Kafka"
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
index 35e9f95e2be..2c72daec7b5 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
@@ -2,4 +2,8 @@
   "name" : "John Doe",
   "age" : 30,
   "favorite" : "Apache NiFi"
+}, {
+  "name" : "Jane Smith",
+  "age" : 25,
+  "favorite" : "Apache Kafka"
 } ]
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
index 6a1b8d5b88c..bc04f52328c 100644
--- 
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
+++ 
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
@@ -2,4 +2,8 @@
   "full_name" : "John Doe",
   "age" : 30,
   "app" : "Apache NiFi"
+}, {
+  "full_name" : "Jane Smith",
+  "age" : 25,
+  "app" : "Apache Kafka"
 } ]
\ No newline at end of file

Reply via email to