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 7913d74bf2 [hive] Support multiset type in hive writes (#9081)
7913d74bf2 is described below

commit 7913d74bf201fce0d7b54876a0935ffa68ce5594
Author: Eunbin Son <[email protected]>
AuthorDate: Thu Aug 6 23:12:03 2026 +0900

    [hive] Support multiset type in hive writes (#9081)
---
 .../java/org/apache/paimon/hive/SchemaVisitor.java | 12 +++++
 .../org/apache/paimon/hive/PaimonSerDeTest.java    | 53 +++++++++++++++++++++-
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git 
a/paimon-hive/paimon-hive-connector-common/src/main/java/org/apache/paimon/hive/SchemaVisitor.java
 
b/paimon-hive/paimon-hive-connector-common/src/main/java/org/apache/paimon/hive/SchemaVisitor.java
index 093ddc93e1..eba7d37b5e 100644
--- 
a/paimon-hive/paimon-hive-connector-common/src/main/java/org/apache/paimon/hive/SchemaVisitor.java
+++ 
b/paimon-hive/paimon-hive-connector-common/src/main/java/org/apache/paimon/hive/SchemaVisitor.java
@@ -21,7 +21,9 @@ package org.apache.paimon.hive;
 import org.apache.paimon.types.ArrayType;
 import org.apache.paimon.types.DataField;
 import org.apache.paimon.types.DataType;
+import org.apache.paimon.types.IntType;
 import org.apache.paimon.types.MapType;
+import org.apache.paimon.types.MultisetType;
 import org.apache.paimon.types.RowType;
 
 import org.apache.paimon.shade.guava30.com.google.common.collect.Lists;
@@ -90,6 +92,16 @@ public abstract class SchemaVisitor<P, R> {
                 valueResult = visit(map.getValueType(), valuePartner, visitor, 
accessors);
                 return visitor.map(map, partner, keyResult, valueResult);
 
+            case MULTISET:
+                // a multiset is represented as a map from element to its 
count, the same mapping
+                // used by PaimonObjectInspectorFactory on the read side
+                MultisetType multiset = (MultisetType) type;
+                return visit(
+                        new MapType(type.isNullable(), 
multiset.getElementType(), new IntType()),
+                        partner,
+                        visitor,
+                        accessors);
+
             default:
                 return visitor.primitive(type, partner);
         }
diff --git 
a/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/hive/PaimonSerDeTest.java
 
b/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/hive/PaimonSerDeTest.java
index 53e4fafa6b..449c4ce213 100644
--- 
a/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/hive/PaimonSerDeTest.java
+++ 
b/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/hive/PaimonSerDeTest.java
@@ -19,20 +19,31 @@
 package org.apache.paimon.hive;
 
 import org.apache.paimon.data.GenericRow;
+import org.apache.paimon.data.InternalMap;
+import org.apache.paimon.data.InternalRow;
 import org.apache.paimon.fs.Path;
 import org.apache.paimon.fs.local.LocalFileIO;
 import org.apache.paimon.hive.objectinspector.PaimonInternalRowObjectInspector;
 import org.apache.paimon.schema.Schema;
 import org.apache.paimon.schema.SchemaManager;
+import org.apache.paimon.types.DataType;
+import org.apache.paimon.types.DataTypes;
+import org.apache.paimon.types.RowType;
 
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
 import org.apache.hadoop.hive.serde2.objectinspector.StructField;
+import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 
 import static 
org.apache.paimon.hive.RandomGenericRowDataGenerator.FIELD_COMMENTS;
@@ -71,11 +82,51 @@ public class PaimonSerDeTest {
         assertThat(serDe.deserialize(container)).isEqualTo(rowData);
     }
 
+    @Test
+    public void testSerializeMultiset() throws Exception {
+        RowType rowType =
+                RowType.of(
+                        new DataType[] {DataTypes.INT(), 
DataTypes.MULTISET(DataTypes.STRING())},
+                        new String[] {"id", "tags"});
+        PaimonSerDe serDe = createInitializedSerDe(rowType);
+
+        // hive represents a multiset column as map<element, count>
+        StructObjectInspector sourceInspector =
+                ObjectInspectorFactory.getStandardStructObjectInspector(
+                        Arrays.asList("id", "tags"),
+                        Arrays.asList(
+                                
PrimitiveObjectInspectorFactory.javaIntObjectInspector,
+                                
ObjectInspectorFactory.getStandardMapObjectInspector(
+                                        
PrimitiveObjectInspectorFactory.javaStringObjectInspector,
+                                        
PrimitiveObjectInspectorFactory.javaIntObjectInspector)));
+
+        Map<String, Integer> tags = new LinkedHashMap<>();
+        tags.put("apple", 2);
+        tags.put("banana", 1);
+
+        InternalRow row =
+                ((RowDataContainer) serDe.serialize(Arrays.asList(1, tags), 
sourceInspector)).get();
+
+        assertThat(row.getInt(0)).isEqualTo(1);
+        InternalMap actual = row.getMap(1);
+        assertThat(actual.size()).isEqualTo(tags.size());
+        Map<String, Integer> actualTags = new HashMap<>();
+        for (int i = 0; i < actual.size(); i++) {
+            actualTags.put(
+                    actual.keyArray().getString(i).toString(), 
actual.valueArray().getInt(i));
+        }
+        assertThat(actualTags).isEqualTo(tags);
+    }
+
     private PaimonSerDe createInitializedSerDe() throws Exception {
+        return createInitializedSerDe(ROW_TYPE);
+    }
+
+    private PaimonSerDe createInitializedSerDe(RowType rowType) throws 
Exception {
         new SchemaManager(LocalFileIO.create(), new Path(tempDir.toString()))
                 .createTable(
                         new Schema(
-                                ROW_TYPE.getFields(),
+                                rowType.getFields(),
                                 Collections.emptyList(),
                                 Collections.emptyList(),
                                 new HashMap<>(),

Reply via email to