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 548169cbe8 [mosaic] Update mosaic dependency to 0.2.0 (#8264)
548169cbe8 is described below
commit 548169cbe884d4d15bf7b7a21ad95f90385f5790
Author: jianguotian <[email protected]>
AuthorDate: Wed Jun 17 20:10:52 2026 +0800
[mosaic] Update mosaic dependency to 0.2.0 (#8264)
Mosaic now supports ARRAY and MAP, starting from version 0.2.0 (released
on Maven Central). #8178 already let these types pass schema validation,
but kept the dependency on 0.1.0, so ARRAY/MAP columns still could not
actually be written or read.
This PR updates the mosaic dependency from 0.1.0 to 0.2.0, so ARRAY and
MAP columns can be written and read for real.
---
paimon-mosaic/pom.xml | 2 +-
.../format/mosaic/MosaicFormatReadWriteTest.java | 84 +++++++++++++++++++++-
2 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/paimon-mosaic/pom.xml b/paimon-mosaic/pom.xml
index a265af539b..39b11114bc 100644
--- a/paimon-mosaic/pom.xml
+++ b/paimon-mosaic/pom.xml
@@ -35,7 +35,7 @@ under the License.
<dependency>
<groupId>org.apache.paimon</groupId>
<artifactId>mosaic</artifactId>
- <version>0.1.0</version>
+ <version>0.2.0</version>
</dependency>
<dependency>
diff --git
a/paimon-mosaic/src/test/java/org/apache/paimon/format/mosaic/MosaicFormatReadWriteTest.java
b/paimon-mosaic/src/test/java/org/apache/paimon/format/mosaic/MosaicFormatReadWriteTest.java
index 41f632b3ee..c286c74f5b 100644
---
a/paimon-mosaic/src/test/java/org/apache/paimon/format/mosaic/MosaicFormatReadWriteTest.java
+++
b/paimon-mosaic/src/test/java/org/apache/paimon/format/mosaic/MosaicFormatReadWriteTest.java
@@ -20,19 +20,30 @@ package org.apache.paimon.format.mosaic;
import org.apache.paimon.data.BinaryString;
import org.apache.paimon.data.Decimal;
+import org.apache.paimon.data.GenericArray;
+import org.apache.paimon.data.GenericMap;
import org.apache.paimon.data.GenericRow;
+import org.apache.paimon.data.InternalMap;
import org.apache.paimon.data.InternalRow;
import org.apache.paimon.data.Timestamp;
import org.apache.paimon.format.FileFormat;
import org.apache.paimon.format.FileFormatFactory;
import org.apache.paimon.format.FormatReadWriteTest;
+import org.apache.paimon.format.FormatReaderContext;
+import org.apache.paimon.format.FormatWriterFactory;
import org.apache.paimon.options.Options;
+import org.apache.paimon.reader.RecordReader;
import org.apache.paimon.types.DataTypes;
import org.apache.paimon.types.RowType;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
@@ -81,6 +92,8 @@ class MosaicFormatReadWriteTest extends FormatReadWriteTest {
.field("f_timestamp6", DataTypes.TIMESTAMP(6))
.field("f_decimal_5_2", DataTypes.DECIMAL(5, 2))
.field("f_decimal_20_0", DataTypes.DECIMAL(20, 0))
+ .field("f_array", DataTypes.ARRAY(DataTypes.INT()))
+ .field("f_map", DataTypes.MAP(DataTypes.STRING(),
DataTypes.INT()))
.build();
}
@@ -100,12 +113,21 @@ class MosaicFormatReadWriteTest extends
FormatReadWriteTest {
Timestamp.fromEpochMillis(1700000000000L),
Timestamp.fromMicros(1700000000000000L),
Decimal.fromBigDecimal(new BigDecimal("123.45"), 5, 2),
- Decimal.fromBigDecimal(new BigDecimal("12345678901234567890"),
20, 0));
+ Decimal.fromBigDecimal(new BigDecimal("12345678901234567890"),
20, 0),
+ new GenericArray(new int[] {10, 20, 30}),
+ new GenericMap(buildMap()));
+ }
+
+ private static Map<BinaryString, Integer> buildMap() {
+ Map<BinaryString, Integer> map = new HashMap<>();
+ map.put(BinaryString.fromString("k1"), 1);
+ map.put(BinaryString.fromString("k2"), 2);
+ return map;
}
@Override
protected void validateFullTypesResult(InternalRow actual, InternalRow
expected) {
- for (int i = 0; i < 14; i++) {
+ for (int i = 0; i < 16; i++) {
if (expected.isNullAt(i)) {
assertThat(actual.isNullAt(i)).isTrue();
}
@@ -124,6 +146,64 @@ class MosaicFormatReadWriteTest extends
FormatReadWriteTest {
assertThat(actual.getTimestamp(11,
6)).isEqualTo(expected.getTimestamp(11, 6));
assertThat(actual.getDecimal(12, 5,
2)).isEqualTo(expected.getDecimal(12, 5, 2));
assertThat(actual.getDecimal(13, 20,
0)).isEqualTo(expected.getDecimal(13, 20, 0));
+
assertThat(actual.getArray(14).toIntArray()).isEqualTo(expected.getArray(14).toIntArray());
+
assertThat(toJavaMap(actual.getMap(15))).isEqualTo(toJavaMap(expected.getMap(15)));
+ }
+
+ private static Map<String, Integer> toJavaMap(InternalMap m) {
+ Map<String, Integer> out = new HashMap<>();
+ for (int i = 0; i < m.size(); i++) {
+ out.put(m.keyArray().getString(i).toString(),
m.valueArray().getInt(i));
+ }
+ return out;
+ }
+
+ /** ARRAY/MAP with null fields, null elements and empty collections. */
+ @Test
+ void testArrayMapNullAndEmpty() throws Exception {
+ RowType rowType =
+ RowType.builder()
+ .field("f_arr", DataTypes.ARRAY(DataTypes.STRING()))
+ .field("f_map", DataTypes.MAP(DataTypes.INT(),
DataTypes.STRING()))
+ .build();
+
+ Map<Integer, BinaryString> m0 = new HashMap<>();
+ m0.put(1, BinaryString.fromString("a"));
+ InternalRow populated =
+ GenericRow.of(
+ new GenericArray(new BinaryString[]
{BinaryString.fromString("x"), null}),
+ new GenericMap(m0));
+ InternalRow nulls = GenericRow.of(null, null);
+ InternalRow empties =
+ GenericRow.of(
+ new GenericArray(new BinaryString[0]), new
GenericMap(new HashMap<>()));
+
+ FormatWriterFactory factory =
fileFormat().createWriterFactory(rowType);
+ write(factory, file, populated, nulls, empties);
+
+ // Materialize inside the callback: reader reuses native-backed
vectors per batch.
+ List<String> arrSummary = new ArrayList<>();
+ List<String> mapSummary = new ArrayList<>();
+ try (RecordReader<InternalRow> reader =
+ fileFormat()
+ .createReaderFactory(rowType, rowType, new
ArrayList<>())
+ .createReader(
+ new FormatReaderContext(fileIO, file,
fileIO.getFileSize(file)))) {
+ reader.forEachRemaining(
+ r -> {
+ arrSummary.add(
+ r.isNullAt(0)
+ ? "null"
+ : r.getArray(0).size()
+ + ":"
+ + (r.getArray(0).size() > 1
+ &&
r.getArray(0).isNullAt(1)));
+ mapSummary.add(r.isNullAt(1) ? "null" :
String.valueOf(r.getMap(1).size()));
+ });
+ }
+
+ assertThat(arrSummary).containsExactly("2:true", "null", "0:false");
+ assertThat(mapSummary).containsExactly("1", "null", "0");
}
private static boolean isNativeAvailable() {