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

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new f80d348b7b [format] Compare array wrapper-group names 
case-insensitively in ParquetReaderUtil (#9568)
f80d348b7b is described below

commit f80d348b7bc449a7e9c47a642adcc0cde2248ef1
Author: YangJie <[email protected]>
AuthorDate: Thu Sep 3 04:26:17 2026 -0400

    [format] Compare array wrapper-group names case-insensitively in 
ParquetReaderUtil (#9568)
---
 .../format/parquet/reader/ParquetReaderUtil.java   |  5 +-
 .../parquet/ParquetCaseInsensitiveReadTest.java    | 61 ++++++++++++++++++++++
 2 files changed, 64 insertions(+), 2 deletions(-)

diff --git 
a/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/ParquetReaderUtil.java
 
b/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/ParquetReaderUtil.java
index 60c29f55a9..48f98b785b 100644
--- 
a/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/ParquetReaderUtil.java
+++ 
b/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/ParquetReaderUtil.java
@@ -44,7 +44,6 @@ import org.apache.parquet.schema.Type;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 import java.util.stream.Collectors;
 
 import static 
org.apache.paimon.format.parquet.ParquetSchemaConverter.convertToPaimonField;
@@ -168,7 +167,9 @@ public class ParquetReaderUtil {
             if (columnIO instanceof GroupColumnIO) {
                 GroupColumnIO groupColumnIO = (GroupColumnIO) columnIO;
                 if (!StringUtils.isNullOrWhitespaceOnly(fieldName)) {
-                    while (!Objects.equals(groupColumnIO.getName(), 
fieldName)) {
+                    // Column lookup is case-insensitive; the wrapper-group 
names can
+                    // therefore differ in case from the requested field name.
+                    while 
(!groupColumnIO.getName().equalsIgnoreCase(fieldName)) {
                         groupColumnIO = (GroupColumnIO) 
groupColumnIO.getChild(0);
                     }
                     elementTypeColumnIO = groupColumnIO;
diff --git 
a/paimon-format/src/test/java/org/apache/paimon/format/parquet/ParquetCaseInsensitiveReadTest.java
 
b/paimon-format/src/test/java/org/apache/paimon/format/parquet/ParquetCaseInsensitiveReadTest.java
index 33a6559a44..5517f1914e 100644
--- 
a/paimon-format/src/test/java/org/apache/paimon/format/parquet/ParquetCaseInsensitiveReadTest.java
+++ 
b/paimon-format/src/test/java/org/apache/paimon/format/parquet/ParquetCaseInsensitiveReadTest.java
@@ -18,7 +18,10 @@
 
 package org.apache.paimon.format.parquet;
 
+import org.apache.paimon.data.BinaryString;
+import org.apache.paimon.data.GenericArray;
 import org.apache.paimon.data.GenericRow;
+import org.apache.paimon.data.InternalArray;
 import org.apache.paimon.data.InternalRow;
 import org.apache.paimon.format.FormatReaderContext;
 import org.apache.paimon.fs.Path;
@@ -118,6 +121,29 @@ class ParquetCaseInsensitiveReadTest {
         assertThat(nested.getLong(1)).isEqualTo(20L);
     }
 
+    @Test
+    void testArrayCaseInsensitiveColumnMatching() throws Exception {
+        Path path = writeArrayMixedCaseParquet();
+
+        // Lowercase name for a column the file spells "Tags" + 
caseSensitive=false.
+        RowType readType =
+                RowType.builder().field("tags", 
DataTypes.ARRAY(DataTypes.STRING())).build();
+
+        List<InternalRow> rows = read(path, readType, false);
+
+        assertThat(rows).hasSize(2);
+        InternalArray first = rows.get(0).getArray(0);
+        assertThat(first.size()).isEqualTo(2);
+        assertThat(first.getString(0).toString()).isEqualTo("a");
+        assertThat(first.getString(1).toString()).isEqualTo("b");
+        // A second row of a different length, so a wrong offset and a wrong 
length differ.
+        InternalArray second = rows.get(1).getArray(0);
+        assertThat(second.size()).isEqualTo(3);
+        assertThat(second.getString(0).toString()).isEqualTo("c");
+        assertThat(second.getString(1).toString()).isEqualTo("d");
+        assertThat(second.getString(2).toString()).isEqualTo("e");
+    }
+
     @Test
     void testAmbiguousCaseInsensitiveMatchFails() throws Exception {
         Path path = writeDuplicateCaseParquet();
@@ -164,6 +190,14 @@ class ParquetCaseInsensitiveReadTest {
                     RowType child = (RowType) rowType.getTypeAt(i);
                     values[i] = copy(row.getRow(i, child.getFieldCount()), 
child);
                     break;
+                case ARRAY:
+                    InternalArray array = row.getArray(i);
+                    BinaryString[] strings = new BinaryString[array.size()];
+                    for (int j = 0; j < array.size(); j++) {
+                        strings[j] = array.isNullAt(j) ? null : 
array.getString(j).copy();
+                    }
+                    values[i] = new GenericArray(strings);
+                    break;
                 default:
                     throw new UnsupportedOperationException(
                             "Unhandled type in test: " + rowType.getTypeAt(i));
@@ -242,6 +276,33 @@ class ParquetCaseInsensitiveReadTest {
                                 factory.newGroup().append("col", 
"a").append("COL", "b")));
     }
 
+    private Path writeArrayMixedCaseParquet() throws Exception {
+        MessageType schema =
+                MessageTypeParser.parseMessageType(
+                        "message root {\n"
+                                + "  optional group Tags (LIST) {\n"
+                                + "    repeated group list {\n"
+                                + "      optional binary element (UTF8);\n"
+                                + "    }\n"
+                                + "  }\n"
+                                + "}");
+
+        return write(
+                schema,
+                factory -> {
+                    List<Group> groups = new ArrayList<>();
+                    for (String[] pair : new String[][] {{"a", "b"}, {"c", 
"d", "e"}}) {
+                        Group g = factory.newGroup();
+                        Group tags = g.addGroup("Tags");
+                        for (String v : pair) {
+                            tags.addGroup("list").append("element", v);
+                        }
+                        groups.add(g);
+                    }
+                    return groups;
+                });
+    }
+
     private interface GroupSupplier {
         List<Group> get(SimpleGroupFactory factory);
     }

Reply via email to