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 ec1c37b1ee [core] Reject deletion of the main branch (#10825)
ec1c37b1ee is described below

commit ec1c37b1eeb8cabc898b6daf0ea40ede9637d9dc
Author: Jingsong Lee <[email protected]>
AuthorDate: Tue Oct 27 12:54:45 2026 +0800

    [core] Reject deletion of the main branch (#10825)
---
 .../paimon/utils/FileSystemBranchManager.java      |  2 +
 .../paimon/utils/FileSystemBranchManagerTest.java  | 61 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git 
a/paimon-core/src/main/java/org/apache/paimon/utils/FileSystemBranchManager.java
 
b/paimon-core/src/main/java/org/apache/paimon/utils/FileSystemBranchManager.java
index 5975f3f076..872d864eeb 100644
--- 
a/paimon-core/src/main/java/org/apache/paimon/utils/FileSystemBranchManager.java
+++ 
b/paimon-core/src/main/java/org/apache/paimon/utils/FileSystemBranchManager.java
@@ -146,6 +146,8 @@ public class FileSystemBranchManager implements 
BranchManager {
 
     @Override
     public void dropBranch(String branchName) {
+        checkArgument(
+                !BranchManager.isMainBranch(branchName), "The main branch 
cannot be deleted.");
         checkArgument(branchExists(branchName), "Branch name '%s' doesn't 
exist.", branchName);
         try {
             // Delete branch directory
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/utils/FileSystemBranchManagerTest.java
 
b/paimon-core/src/test/java/org/apache/paimon/utils/FileSystemBranchManagerTest.java
index b2aba70b2b..ed4cf8d178 100644
--- 
a/paimon-core/src/test/java/org/apache/paimon/utils/FileSystemBranchManagerTest.java
+++ 
b/paimon-core/src/test/java/org/apache/paimon/utils/FileSystemBranchManagerTest.java
@@ -18,20 +18,36 @@
 
 package org.apache.paimon.utils;
 
+import org.apache.paimon.data.GenericRow;
 import org.apache.paimon.fs.FileIO;
 import org.apache.paimon.fs.FileIOFinder;
 import org.apache.paimon.fs.Path;
 import org.apache.paimon.schema.FileSystemSchemaManager;
 import org.apache.paimon.schema.Schema;
+import org.apache.paimon.schema.SchemaChange;
 import org.apache.paimon.schema.SchemaManager;
+import org.apache.paimon.table.FileStoreTable;
+import org.apache.paimon.table.FileStoreTableFactory;
+import org.apache.paimon.table.sink.BatchTableCommit;
+import org.apache.paimon.table.sink.BatchTableWrite;
+import org.apache.paimon.table.sink.BatchWriteBuilder;
 import org.apache.paimon.types.DataTypes;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
+import java.nio.file.Files;
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import static org.apache.paimon.CoreOptions.BUCKET;
+import static org.apache.paimon.catalog.Identifier.DEFAULT_MAIN_BRANCH;
+import static org.apache.paimon.table.SimpleTableTestBase.getResult;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -73,6 +89,51 @@ class FileSystemBranchManagerTest {
                         fileIO, tablePath, snapshotManager, tagManager, 
schemaManager, null);
     }
 
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    void testDeleteMainBranchPreservesTable(boolean useTableApi) throws 
Exception {
+        schemaManager.commitChanges(SchemaChange.setOption(BUCKET.key(), "1"));
+        FileStoreTable table = FileStoreTableFactory.create(fileIO, tablePath);
+        BatchWriteBuilder writeBuilder = table.newBatchWriteBuilder();
+        try (BatchTableWrite write = writeBuilder.newWrite();
+                BatchTableCommit commit = writeBuilder.newCommit()) {
+            write.write(GenericRow.of(1, 10, 100));
+            commit.commit(write.prepareCommit());
+        }
+        table.createTag("tag1", 1);
+        table.createBranch("branch1", "tag1");
+        Set<java.nio.file.Path> retainedFiles;
+        try (Stream<java.nio.file.Path> files = Files.walk(tempDir)) {
+            retainedFiles = 
files.filter(Files::isRegularFile).collect(Collectors.toSet());
+        }
+
+        assertThatThrownBy(
+                        () -> {
+                            if (useTableApi) {
+                                table.deleteBranch(DEFAULT_MAIN_BRANCH);
+                            } else {
+                                branchManager.dropBranch(DEFAULT_MAIN_BRANCH);
+                            }
+                        })
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessage("The main branch cannot be deleted.");
+
+        try (Stream<java.nio.file.Path> files = Files.walk(tempDir)) {
+            
assertThat(files.filter(Files::isRegularFile).collect(Collectors.toSet()))
+                    .containsExactlyInAnyOrderElementsOf(retainedFiles);
+        }
+        FileStoreTable reloaded = FileStoreTableFactory.create(fileIO, 
tablePath);
+        assertThat(reloaded.snapshotManager().snapshotExists(1)).isTrue();
+        assertThat(reloaded.tagManager().tagExists("tag1")).isTrue();
+        assertThat(reloaded.branchManager().branchExists("branch1")).isTrue();
+        assertThat(
+                        getResult(
+                                reloaded.newRead(),
+                                
reloaded.newReadBuilder().newScan().plan().splits(),
+                                row -> row.getInt(0) + "," + row.getInt(1) + 
"," + row.getInt(2)))
+                .containsExactly("1,10,100");
+    }
+
     @Test
     void testRenameBranchBasic() {
         // Create a branch

Reply via email to