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 142f8239be [core] Preserve index manifest compatibility (#9004)
142f8239be is described below

commit 142f8239be9334c9d7621bacdf8fb63840b9bee1
Author: Jingsong Lee <[email protected]>
AuthorDate: Mon Aug 3 21:22:39 2026 +0800

    [core] Preserve index manifest compatibility (#9004)
---
 .../manifest/IndexManifestEntrySerializer.java     |  9 ++--
 .../manifest/IndexManifestEntrySerializerTest.java | 33 ++++----------
 .../manifest/IndexManifestFileHandlerTest.java     | 51 ++++++++++++++++++++++
 3 files changed, 63 insertions(+), 30 deletions(-)

diff --git 
a/paimon-core/src/main/java/org/apache/paimon/manifest/IndexManifestEntrySerializer.java
 
b/paimon-core/src/main/java/org/apache/paimon/manifest/IndexManifestEntrySerializer.java
index d8649dab2f..d6979de802 100644
--- 
a/paimon-core/src/main/java/org/apache/paimon/manifest/IndexManifestEntrySerializer.java
+++ 
b/paimon-core/src/main/java/org/apache/paimon/manifest/IndexManifestEntrySerializer.java
@@ -43,7 +43,7 @@ public class IndexManifestEntrySerializer extends 
VersionedObjectSerializer<Inde
 
     @Override
     public int getVersion() {
-        return 2;
+        return 1;
     }
 
     @Override
@@ -77,21 +77,20 @@ public class IndexManifestEntrySerializer extends 
VersionedObjectSerializer<Inde
 
     @Override
     public IndexManifestEntry convertFrom(int version, InternalRow row) {
-        if (version < 1 || version > 2) {
+        if (version != 1) {
             throw new UnsupportedOperationException("Unsupported version: " + 
version);
         }
 
         GlobalIndexMeta globalIndexMeta = null;
         if (!row.isNullAt(9)) {
-            InternalRow globalIndexRow = row.getRow(9, version == 1 ? 5 : 6);
+            InternalRow globalIndexRow = row.getRow(9, 
GlobalIndexMeta.SCHEMA.getFieldCount());
             long rowRangeStart = globalIndexRow.getLong(0);
             long rowRangeEnd = globalIndexRow.getLong(1);
             int indexFieldId = globalIndexRow.getInt(2);
             int[] extralFields =
                     globalIndexRow.isNullAt(3) ? null : 
globalIndexRow.getArray(3).toIntArray();
             byte[] indexMeta = globalIndexRow.isNullAt(4) ? null : 
globalIndexRow.getBinary(4);
-            byte[] sourceMeta =
-                    version == 1 || globalIndexRow.isNullAt(5) ? null : 
globalIndexRow.getBinary(5);
+            byte[] sourceMeta = globalIndexRow.isNullAt(5) ? null : 
globalIndexRow.getBinary(5);
             globalIndexMeta =
                     new GlobalIndexMeta(
                             rowRangeStart,
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestEntrySerializerTest.java
 
b/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestEntrySerializerTest.java
index d7cccdd880..28be88b809 100644
--- 
a/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestEntrySerializerTest.java
+++ 
b/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestEntrySerializerTest.java
@@ -20,20 +20,13 @@ package org.apache.paimon.manifest;
 
 import org.apache.paimon.data.BinaryRow;
 import org.apache.paimon.data.GenericRow;
-import org.apache.paimon.data.InternalRow;
-import org.apache.paimon.data.JoinedRow;
-import org.apache.paimon.data.serializer.InternalRowSerializer;
-import org.apache.paimon.data.serializer.InternalSerializers;
 import org.apache.paimon.index.GlobalIndexMeta;
 import org.apache.paimon.index.IndexFileMeta;
-import org.apache.paimon.io.DataOutputViewStreamWrapper;
 import org.apache.paimon.utils.ObjectSerializer;
 import org.apache.paimon.utils.ObjectSerializerTestBase;
-import org.apache.paimon.utils.VersionedObjectSerializer;
 
 import org.junit.jupiter.api.Test;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.Random;
 
@@ -45,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 public class IndexManifestEntrySerializerTest extends 
ObjectSerializerTestBase<IndexManifestEntry> {
 
     @Test
-    void testReadsGlobalIndexWithoutSourceMeta() throws IOException {
+    void testReadsGlobalIndexWithoutSourceMeta() {
         IndexManifestEntrySerializer serializer = new 
IndexManifestEntrySerializer();
         IndexManifestEntry entry =
                 new IndexManifestEntry(
@@ -60,25 +53,14 @@ public class IndexManifestEntrySerializerTest extends 
ObjectSerializerTestBase<I
                                 new GlobalIndexMeta(0, 9, 7, null, new byte[] 
{1}),
                                 null));
         GenericRow serialized = (GenericRow) serializer.convertTo(entry);
-        InternalRowSerializer legacyGlobalIndexSerializer =
-                InternalSerializers.create(
-                        GlobalIndexMeta.SCHEMA.copy(
-                                GlobalIndexMeta.SCHEMA.getFields().subList(0, 
5)));
-        BinaryRow legacyGlobalIndexRow =
-                legacyGlobalIndexSerializer
-                        .toBinaryRow(GenericRow.of(0L, 9L, 7, null, new byte[] 
{1}))
-                        .copy();
-        serialized.setField(9, legacyGlobalIndexRow);
-
-        InternalRow version1Row = new JoinedRow().replace(GenericRow.of(1), 
serialized);
-        InternalRowSerializer versionedRowSerializer =
-                InternalSerializers.create(
-                        
VersionedObjectSerializer.versionType(IndexManifestEntry.SCHEMA));
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        versionedRowSerializer.serialize(version1Row, new 
DataOutputViewStreamWrapper(out));
+        assertThat(serialized.getRow(9, 
GlobalIndexMeta.SCHEMA.getFieldCount()).getFieldCount())
+                .isEqualTo(6);
 
         GlobalIndexMeta restored =
-                
serializer.deserializeFromBytes(out.toByteArray()).indexFile().globalIndexMeta();
+                serializer
+                        .convertFrom(serializer.getVersion(), serialized)
+                        .indexFile()
+                        .globalIndexMeta();
 
         assertThat(restored.indexMeta()).containsExactly(1);
         assertThat(restored.sourceMeta()).isNull();
@@ -87,6 +69,7 @@ public class IndexManifestEntrySerializerTest extends 
ObjectSerializerTestBase<I
     @Test
     void testGlobalIndexSourceMetaRoundTrip() throws IOException {
         IndexManifestEntrySerializer serializer = new 
IndexManifestEntrySerializer();
+        assertThat(serializer.getVersion()).isEqualTo(1);
         IndexManifestEntry entry =
                 new IndexManifestEntry(
                         FileKind.ADD,
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestFileHandlerTest.java
 
b/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestFileHandlerTest.java
index cfcc896525..c022d05b72 100644
--- 
a/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestFileHandlerTest.java
+++ 
b/paimon-core/src/test/java/org/apache/paimon/manifest/IndexManifestFileHandlerTest.java
@@ -20,19 +20,28 @@ package org.apache.paimon.manifest;
 
 import org.apache.paimon.TestAppendFileStore;
 import org.apache.paimon.data.BinaryRow;
+import org.apache.paimon.data.InternalRow;
 import org.apache.paimon.format.FileFormat;
+import org.apache.paimon.format.FormatReaderFactory;
+import org.apache.paimon.fs.Path;
 import org.apache.paimon.index.GlobalIndexMeta;
 import org.apache.paimon.index.IndexFileMeta;
 import org.apache.paimon.table.BucketMode;
+import org.apache.paimon.types.DataField;
+import org.apache.paimon.types.RowType;
+import org.apache.paimon.utils.CloseableIterator;
+import org.apache.paimon.utils.VersionedObjectSerializer;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 
 import static 
org.apache.paimon.index.IndexFileMetaSerializerTest.randomDeletionVectorIndexFile;
+import static org.apache.paimon.utils.FileUtils.createFormatReader;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -118,6 +127,48 @@ public class IndexManifestFileHandlerTest {
         assertThat(entries.contains(entry4)).isTrue();
     }
 
+    @Test
+    public void testNewIndexManifestReadableWithLegacySchema() throws 
Exception {
+        TestAppendFileStore fileStore =
+                TestAppendFileStore.createAppendStore(tempDir, new 
HashMap<>());
+        FileFormat fileFormat = FileFormat.manifestFormat(fileStore.options());
+        IndexManifestFile indexManifestFile =
+                new IndexManifestFile.Factory(
+                                fileStore.fileIO(),
+                                fileFormat,
+                                "zstd",
+                                fileStore.pathFactory(),
+                                null)
+                        .create();
+        IndexManifestFileHandler handler =
+                new IndexManifestFileHandler(indexManifestFile, 
BucketMode.HASH_FIXED);
+
+        String manifestFile = handler.write(null, 
Arrays.asList(pkVectorEntry("btree", "index")));
+
+        RowType legacyGlobalIndexSchema =
+                
GlobalIndexMeta.SCHEMA.copy(GlobalIndexMeta.SCHEMA.getFields().subList(0, 5));
+        List<DataField> legacyEntryFields = new 
ArrayList<>(IndexManifestEntry.SCHEMA.getFields());
+        legacyEntryFields.set(9, 
legacyEntryFields.get(9).newType(legacyGlobalIndexSchema));
+        RowType legacySchema =
+                VersionedObjectSerializer.versionType(new RowType(false, 
legacyEntryFields));
+        FormatReaderFactory legacyReaderFactory =
+                fileFormat.createReaderFactory(legacySchema, legacySchema, new 
ArrayList<>());
+        Path path = 
fileStore.pathFactory().indexManifestFileFactory().toPath(manifestFile);
+
+        try (CloseableIterator<InternalRow> iterator =
+                createFormatReader(fileStore.fileIO(), legacyReaderFactory, 
path, null)
+                        .toCloseableIterator()) {
+            InternalRow row = iterator.next();
+            assertThat(row.getInt(0)).isEqualTo(1);
+            InternalRow globalIndex = row.getRow(10, 5);
+            assertThat(globalIndex.getLong(0)).isEqualTo(0);
+            assertThat(globalIndex.getLong(1)).isEqualTo(1);
+            assertThat(globalIndex.getInt(2)).isEqualTo(1);
+            assertThat(globalIndex.isNullAt(4)).isTrue();
+            assertThat(iterator.hasNext()).isFalse();
+        }
+    }
+
     @Test
     public void testGlobalIndexOverlappingRangeRejectedWhenPreviousFileKept() 
throws Exception {
         TestAppendFileStore fileStore =

Reply via email to