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