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 2a5a256046 [core] Avoid strict-mode conflicts for index-only compact
(#8996)
2a5a256046 is described below
commit 2a5a2560460357d3dba64d69496f412d5090a5da
Author: LsomeYeah <[email protected]>
AuthorDate: Mon Aug 3 18:01:37 2026 +0800
[core] Avoid strict-mode conflicts for index-only compact (#8996)
---
.../paimon/operation/commit/StrictModeChecker.java | 19 ++++--
.../apache/paimon/table/sink/TableCommitTest.java | 77 ++++++++++++++++++++++
2 files changed, 91 insertions(+), 5 deletions(-)
diff --git
a/paimon-core/src/main/java/org/apache/paimon/operation/commit/StrictModeChecker.java
b/paimon-core/src/main/java/org/apache/paimon/operation/commit/StrictModeChecker.java
index fa2a972051..52944ea713 100644
---
a/paimon-core/src/main/java/org/apache/paimon/operation/commit/StrictModeChecker.java
+++
b/paimon-core/src/main/java/org/apache/paimon/operation/commit/StrictModeChecker.java
@@ -68,7 +68,13 @@ public class StrictModeChecker {
}
if (snapshot.commitKind() == CommitKind.COMPACT
|| snapshot.commitKind() == CommitKind.OVERWRITE) {
- if (hasOverlappedPartition(snapshot, newPartitions)) {
+ boolean hasOverlap = hasOverlappedDataPartition(snapshot,
newPartitions);
+ // OVERWRITE may contain logical changes represented only by
deletion vectors,
+ // while index-only COMPACT does not change table data.
+ if (!hasOverlap && snapshot.commitKind() ==
CommitKind.OVERWRITE) {
+ hasOverlap = hasOverlappedIndexPartition(snapshot,
newPartitions);
+ }
+ if (hasOverlap) {
throw new RuntimeException(
String.format(
"When trying to commit snapshot %d, "
@@ -109,7 +115,7 @@ public class StrictModeChecker {
}
}
- private boolean hasOverlappedPartition(Snapshot snapshot, Set<BinaryRow>
newPartitions) {
+ private boolean hasOverlappedDataPartition(Snapshot snapshot,
Set<BinaryRow> newPartitions) {
if (newPartitions.isEmpty()) {
return false;
}
@@ -120,10 +126,13 @@ public class StrictModeChecker {
.withKind(ScanMode.DELTA)
.dropStats()
.readFileIterator();
- if (hasOverlappedPartition(entries, newPartitions)) {
- return true;
- }
+ return hasOverlappedPartition(entries, newPartitions);
+ }
+ private boolean hasOverlappedIndexPartition(Snapshot snapshot,
Set<BinaryRow> newPartitions) {
+ if (newPartitions.isEmpty()) {
+ return false;
+ }
String indexManifest = snapshot.indexManifest();
if (indexManifest == null) {
return false;
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/sink/TableCommitTest.java
b/paimon-core/src/test/java/org/apache/paimon/table/sink/TableCommitTest.java
index 25abbaf12b..ee11348b31 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/sink/TableCommitTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/sink/TableCommitTest.java
@@ -25,6 +25,7 @@ import org.apache.paimon.data.GenericRow;
import org.apache.paimon.deletionvectors.BucketedDvMaintainer;
import org.apache.paimon.fs.Path;
import org.apache.paimon.fs.local.LocalFileIO;
+import org.apache.paimon.index.GlobalIndexMeta;
import org.apache.paimon.index.IndexFileHandler;
import org.apache.paimon.index.IndexFileMeta;
import org.apache.paimon.io.CompactIncrement;
@@ -541,6 +542,82 @@ public class TableCommitTest {
commit2.close();
}
+ @Test
+ public void testStrictModeIgnoresIndexOnlyCompact() throws Exception {
+ String path = tempDir.toString();
+ RowType rowType =
+ RowType.of(
+ new DataType[] {DataTypes.INT(), DataTypes.INT(),
DataTypes.BIGINT()},
+ new String[] {"pt", "k", "v"});
+
+ Options options = new Options();
+ options.set(CoreOptions.PATH, path);
+ options.set(CoreOptions.BUCKET, 1);
+ options.set(CoreOptions.BUCKET_KEY, "k");
+ options.set(CoreOptions.NUM_SORTED_RUNS_COMPACTION_TRIGGER, 10);
+ TableSchema tableSchema =
+ SchemaUtils.forceCommit(
+ new SchemaManager(LocalFileIO.create(), new
Path(path)),
+ new Schema(
+ rowType.getFields(),
+ Collections.singletonList("pt"),
+ Collections.emptyList(),
+ options.toMap(),
+ ""));
+ FileStoreTable table =
+ FileStoreTableFactory.create(
+ LocalFileIO.create(),
+ new Path(path),
+ tableSchema,
+ CatalogEnvironment.empty());
+ BinaryRow pt1 = partitionRow(1);
+
+ String user1 = UUID.randomUUID().toString();
+ TableWriteImpl<?> write1 = table.newWrite(user1);
+ TableCommitImpl commit1 = table.newCommit(user1);
+ write1.write(GenericRow.of(1, 0, 0L));
+ commit1.commit(1, write1.prepareCommit(false, 1));
+
+ String user2 = UUID.randomUUID().toString();
+ FileStoreTable tableWithStrict =
+
table.copy(singletonMap(COMMIT_STRICT_MODE_LAST_SAFE_SNAPSHOT.key(), "1"));
+ TableWriteImpl<?> write2 = tableWithStrict.newWrite(user2);
+ TableCommitImpl commit2 = tableWithStrict.newCommit(user2);
+ write2.write(GenericRow.of(1, 1, 1L));
+ write2.compact(pt1, 0, true);
+
+ IndexFileMeta btreeIndex =
+ new IndexFileMeta(
+ "btree",
+ "index-only-compact",
+ 1,
+ 1,
+ new GlobalIndexMeta(0, 0, 1, null, null),
+ null);
+ commit1.commit(
+ 2,
+ Collections.singletonList(
+ new CommitMessageImpl(
+ pt1,
+ 0,
+ 1,
+ DataIncrement.emptyIncrement(),
+ new CompactIncrement(
+ Collections.emptyList(),
+ Collections.emptyList(),
+ Collections.emptyList(),
+ Collections.singletonList(btreeIndex),
+ Collections.emptyList()))));
+
+ assertThatCode(() -> commit2.commit(1, write2.prepareCommit(true, 1)))
+ .doesNotThrowAnyException();
+
+ write1.close();
+ commit1.close();
+ write2.close();
+ commit2.close();
+ }
+
@Test
public void testStrictModeForDvOnlyOverwrite() throws Exception {
// Regression test for the partition-overlap check on DV-only OVERWRITE