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

exceptionfactory 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 d7e92b8705d NIFI-16336 Initialized all field names with inference 
defaults in ExcelStartingRowSchemaInference (#11716)
d7e92b8705d is described below

commit d7e92b8705d1c2eee48aa4d51875b0c6b4d4c362
Author: dan-s1 <[email protected]>
AuthorDate: Mon Sep 28 17:21:33 2026 -0400

    NIFI-16336 Initialized all field names with inference defaults in 
ExcelStartingRowSchemaInference (#11716)
    
    - Initialization ensures a record field type for each field
    
    Signed-off-by: David Handermann <[email protected]>
---
 .../excel/ExcelStartingRowSchemaInference.java     |  5 ++
 .../excel/TestExcelStartingRowSchemaInference.java | 91 +++++++++++++++++++---
 2 files changed, 86 insertions(+), 10 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/main/java/org/apache/nifi/excel/ExcelStartingRowSchemaInference.java
 
b/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/main/java/org/apache/nifi/excel/ExcelStartingRowSchemaInference.java
index 4a6c0f45443..d951f81ef4e 100644
--- 
a/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/main/java/org/apache/nifi/excel/ExcelStartingRowSchemaInference.java
+++ 
b/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/main/java/org/apache/nifi/excel/ExcelStartingRowSchemaInference.java
@@ -69,6 +69,11 @@ public class ExcelStartingRowSchemaInference implements 
SchemaInferenceEngine<Ro
         while ((row = recordSource.next()) != null) {
             if (index == 0) {
                 fieldNames = getFieldNames(firstRow, row);
+                // Initialize the typeMap with all the determined field names 
thereby setting data type defaults for all fields
+                // just in case a specific field data type cannot be inferred.
+                for (String fieldName : fieldNames) {
+                    typeMap.put(fieldName, new FieldTypeInference());
+                }
             } else if (row.getRowNum() == zeroBasedFirstRow) { // skip first 
row of all sheets
                 continue;
             } else {
diff --git 
a/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/test/java/org/apache/nifi/excel/TestExcelStartingRowSchemaInference.java
 
b/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/test/java/org/apache/nifi/excel/TestExcelStartingRowSchemaInference.java
index a6801470c23..104a4171240 100644
--- 
a/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/test/java/org/apache/nifi/excel/TestExcelStartingRowSchemaInference.java
+++ 
b/nifi-extension-bundles/nifi-poi-bundle/nifi-poi-services/src/test/java/org/apache/nifi/excel/TestExcelStartingRowSchemaInference.java
@@ -22,6 +22,7 @@ import org.apache.nifi.logging.ComponentLog;
 import org.apache.nifi.schema.access.SchemaNotFoundException;
 import org.apache.nifi.schema.inference.InferSchemaAccessStrategy;
 import org.apache.nifi.schema.inference.TimeValueInference;
+import org.apache.nifi.serialization.record.DataType;
 import org.apache.nifi.serialization.record.RecordField;
 import org.apache.nifi.serialization.record.RecordFieldType;
 import org.apache.nifi.serialization.record.RecordSchema;
@@ -51,6 +52,7 @@ import java.nio.file.Path;
 import java.time.LocalDate;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 import static java.nio.file.Files.newDirectoryStream;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
@@ -169,6 +171,60 @@ public class TestExcelStartingRowSchemaInference {
         }
     }
 
+    @Test
+    void testWithHeaderWithOnlySingleCellOfData() throws Exception {
+        Object[][] singleSheet = {{"ID", "First", "Middle"}, {}, {}, {},
+                {}, {}, {6}, {}, {}, {}, {}};
+
+        final ByteArrayOutputStream outputStream = createWorkbook(singleSheet);
+
+        try (final InputStream inputStream = new 
ByteArrayInputStream(outputStream.toByteArray())) {
+            final InferSchemaAccessStrategy<?> inferSchemaAccessStrategy = 
getInferSchemaAccessStrategy(RowEvaluationStrategy.STANDARD);
+            final RecordSchema recordSchema = 
inferSchemaAccessStrategy.getSchema(null, inputStream, null);
+
+            assertEquals(List.of("ID", "First", "Middle"), 
recordSchema.getFieldNames());
+            Optional<DataType> optional = recordSchema.getDataType("ID");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.LONG));
+
+            optional = recordSchema.getDataType("First");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+
+            optional = recordSchema.getDataType("Middle");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+        }
+    }
+
+    @ParameterizedTest
+    @EnumSource(RowEvaluationStrategy.class)
+    void 
testWhereLeadingRowAndConfiguredInferenceRowsHaveNoCells(RowEvaluationStrategy 
rowEvaluationStrategy) throws IOException {
+        Object[][] singleSheet = {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
+        final ByteArrayOutputStream outputStream = createWorkbook(singleSheet);
+
+        try (final InputStream inputStream = new 
ByteArrayInputStream(outputStream.toByteArray())) {
+            final InferSchemaAccessStrategy<?> inferSchemaAccessStrategy = 
getInferSchemaAccessStrategy(rowEvaluationStrategy);
+            final IOException ioException = assertThrows(IOException.class, () 
-> inferSchemaAccessStrategy.getSchema(null, inputStream, null));
+            assertInstanceOf(SchemaNotFoundException.class, 
ioException.getCause());
+        }
+    }
+
+    @ParameterizedTest
+    @EnumSource(RowEvaluationStrategy.class)
+    void 
testWhereLeadingRowHasBlankValuesAndConfiguredInferenceRowsHaveNoCells(RowEvaluationStrategy
 rowEvaluationStrategy) throws IOException {
+        Object[][] singleSheet = {{"", "", ""}, {}, {}, {}, {}, {}, {}, {}, 
{}, {}, {}};
+        final ByteArrayOutputStream outputStream = createWorkbook(singleSheet);
+
+        try (final InputStream inputStream = new 
ByteArrayInputStream(outputStream.toByteArray())) {
+            final InferSchemaAccessStrategy<?> inferSchemaAccessStrategy = 
getInferSchemaAccessStrategy(rowEvaluationStrategy);
+            final RecordSchema recordSchema = 
inferSchemaAccessStrategy.getSchema(null, inputStream, null);
+            assertEquals(List.of("column_0", "column_1", "column_2"), 
recordSchema.getFieldNames());
+
+            for (String fieldName : recordSchema.getFieldNames()) {
+                final Optional<DataType> optional = 
recordSchema.getDataType(fieldName);
+                assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+            }
+        }
+    }
+
     @ParameterizedTest
     @EnumSource(RowEvaluationStrategy.class)
     void testWhereConfiguredInferenceRowsAreAllBlank(RowEvaluationStrategy 
rowEvaluationStrategy) throws Exception {
@@ -177,15 +233,23 @@ public class TestExcelStartingRowSchemaInference {
 
         try (final InputStream inputStream = new 
ByteArrayInputStream(outputStream.toByteArray())) {
             final InferSchemaAccessStrategy<?> inferSchemaAccessStrategy = 
getInferSchemaAccessStrategy(rowEvaluationStrategy);
+            final RecordSchema recordSchema = 
inferSchemaAccessStrategy.getSchema(null, inputStream, null);
 
-            switch (rowEvaluationStrategy) {
-                case STANDARD -> {
-                    final IOException ioException = 
assertThrows(IOException.class, () -> inferSchemaAccessStrategy.getSchema(null, 
inputStream, null));
-                    assertInstanceOf(SchemaNotFoundException.class, 
ioException.getCause());
-                    
assertTrue(ioException.getCause().getMessage().contains("empty"));
-                }
-                case ALL -> assertDoesNotThrow(() -> 
inferSchemaAccessStrategy.getSchema(null, inputStream, null));
+            assertEquals(List.of("ID", "First", "Middle"), 
recordSchema.getFieldNames());
+            Optional<DataType> optional = recordSchema.getDataType("ID");
+
+            if (RowEvaluationStrategy.STANDARD.equals(rowEvaluationStrategy)) {
+                assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+            } else {
+                assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.LONG));
             }
+
+            optional = recordSchema.getDataType("First");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+
+            optional = recordSchema.getDataType("Middle");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+
         }
     }
 
@@ -197,10 +261,17 @@ public class TestExcelStartingRowSchemaInference {
 
         try (final InputStream inputStream = new 
ByteArrayInputStream(outputStream.toByteArray())) {
             final InferSchemaAccessStrategy<?> inferSchemaAccessStrategy = 
getInferSchemaAccessStrategy(rowEvaluationStrategy);
+            final RecordSchema recordSchema = 
inferSchemaAccessStrategy.getSchema(null, inputStream, null);
 
-            final IOException ioException = assertThrows(IOException.class, () 
-> inferSchemaAccessStrategy.getSchema(null, inputStream, null));
-            assertInstanceOf(SchemaNotFoundException.class, 
ioException.getCause());
-            assertTrue(ioException.getCause().getMessage().contains("empty"));
+            assertEquals(List.of("ID", "First", "Middle"), 
recordSchema.getFieldNames());
+            Optional<DataType> optional = recordSchema.getDataType("ID");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+
+            optional = recordSchema.getDataType("First");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
+
+            optional = recordSchema.getDataType("Middle");
+            assertTrue(optional.isPresent() && 
optional.get().getFieldType().equals(RecordFieldType.STRING));
         }
     }
 

Reply via email to