This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new acc5a3ddc06 branch-4.2: [feature](iceberg) Add 
iceberg_partition_overwrite_mode session variable (#69010) (#69841)
acc5a3ddc06 is described below

commit acc5a3ddc067d5abe8ba88742a2450ac4a5cd8d6
Author: daidai <[email protected]>
AuthorDate: Thu Nov 5 16:48:52 2026 +0800

    branch-4.2: [feature](iceberg) Add iceberg_partition_overwrite_mode session 
variable (#69010) (#69841)
    
    pick #69010
---
 .../datasource/iceberg/IcebergTransaction.java     |  37 +++++-
 .../commands/insert/IcebergInsertExecutor.java     |   7 +-
 .../java/org/apache/doris/qe/SessionVariable.java  |  37 ++++++
 .../datasource/iceberg/IcebergTransactionTest.java | 131 ++++++++++++++++++++-
 .../commands/insert/IcebergInsertExecutorTest.java |  83 +++++++++++++
 .../org/apache/doris/qe/SessionVariablesTest.java  |  36 ++++++
 .../test_iceberg_partition_overwrite_mode.out      |  22 ++++
 .../iceberg/iceberg_branch_insert_data.groovy      |   3 +
 .../iceberg/test_iceberg_jdbc_catalog.groovy       |   3 +
 .../iceberg/test_iceberg_timestamp_ns.groovy       |   3 +
 .../write/test_iceberg_insert_overwrite.groovy     |   3 +
 ...ceberg_insert_overwrite_with_empty_table.groovy |   3 +
 .../test_iceberg_partition_overwrite_mode.groovy   |  94 +++++++++++++++
 .../test_iceberg_write_branch_dml_boundary.groovy  |   3 +
 .../write/test_iceberg_write_evolution_refs.groovy |   3 +
 .../test_iceberg_write_overwrite_atomicity.groovy  |   3 +
 ...est_iceberg_write_overwrite_delete_files.groovy |   3 +
 .../test_iceberg_write_overwrite_evolution.groovy  |   3 +
 .../test_s3tables_glue_insert_overwrite.groovy     |   3 +
 .../iceberg/test_s3tables_insert_overwrite.groovy  |   3 +
 20 files changed, 478 insertions(+), 5 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergTransaction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergTransaction.java
index 3c2b40ae609..e2291105ef2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergTransaction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergTransaction.java
@@ -27,6 +27,7 @@ import org.apache.doris.datasource.NameMapping;
 import org.apache.doris.datasource.iceberg.helper.IcebergWriterHelper;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.IcebergInsertCommandContext;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.InsertCommandContext;
+import org.apache.doris.qe.SessionVariable;
 import org.apache.doris.thrift.TFileContent;
 import org.apache.doris.thrift.TIcebergCommitData;
 import org.apache.doris.thrift.TUpdateMode;
@@ -96,6 +97,7 @@ public class IcebergTransaction implements Transaction {
     private Optional<Expression> conflictDetectionFilter = Optional.empty();
 
     private IcebergInsertCommandContext insertCtx;
+    private boolean wholeTableOverwrite;
     private Optional<IcebergWriteSchemaContext> writeSchemaContext = 
Optional.empty();
     private String branchName;
     private Long baseSnapshotId;
@@ -147,7 +149,15 @@ public class IcebergTransaction implements Transaction {
     /** Begin an insert against the metadata generation retained during sink 
binding. */
     public void beginInsert(ExternalTable dorisTable, Table targetTable,
             Optional<InsertCommandContext> ctx) throws UserException {
+        beginInsert(dorisTable, targetTable, ctx, 
SessionVariable.ICEBERG_PARTITION_OVERWRITE_MODE_STATIC);
+    }
+
+    /** Capture the session's overwrite scope before executing the write. */
+    public void beginInsert(ExternalTable dorisTable, Table targetTable,
+            Optional<InsertCommandContext> ctx, String partitionOverwriteMode) 
throws UserException {
         this.insertCtx = ctx.map(c -> (IcebergInsertCommandContext) 
c).orElse(null);
+        this.wholeTableOverwrite = 
SessionVariable.ICEBERG_PARTITION_OVERWRITE_MODE_STATIC
+                .equalsIgnoreCase(partitionOverwriteMode);
         this.writeSchemaContext = insertCtx == null
                 ? Optional.empty() : insertCtx.getWriteSchemaContext();
         try {
@@ -158,7 +168,7 @@ public class IcebergTransaction implements Transaction {
                 this.table = createTransactionTable(dorisTable, targetTable);
                 this.branchName = null;
                 this.isRewriteMode = false;
-                this.baseSnapshotId = null;
+                this.baseSnapshotId = getSnapshotIdIfPresent(table);
                 this.hasStagedUpdates = false;
                 // check branch
                 if (insertCtx != null && 
insertCtx.getBranchName().isPresent()) {
@@ -171,6 +181,7 @@ public class IcebergTransaction implements Transaction {
                                 branchName
                                         + " is a tag, not a branch. Tags 
cannot be targets for producing snapshots");
                     }
+                    this.baseSnapshotId = branchRef.snapshotId();
                 }
                 if (writeSchemaContext.isPresent()) {
                     writeSchemaContext.get().validateCurrentSchema(
@@ -664,6 +675,8 @@ public class IcebergTransaction implements Transaction {
             // Check if this is a static partition overwrite
             if (insertCtx != null && insertCtx.isStaticPartitionOverwrite()) {
                 commitStaticPartitionOverwrite(pendingResults);
+            } else if (wholeTableOverwrite) {
+                commitWholeTableOverwrite(pendingResults);
             } else {
                 commitReplaceTxn(pendingResults);
             }
@@ -1135,6 +1148,28 @@ public class IcebergTransaction implements Transaction {
         return referencedDataFiles;
     }
 
+    /** A row filter clears every partition spec, even when the write produces 
no files. */
+    private void commitWholeTableOverwrite(List<WriteResult> pendingResults) {
+        OverwriteFiles overwriteFiles = transaction.newOverwrite();
+        if (branchName != null) {
+            overwriteFiles = overwriteFiles.toBranch(branchName);
+        }
+        overwriteFiles = 
overwriteFiles.scanManifestsWith(ops.getThreadPoolWithPreAuth())
+                .overwriteByRowFilter(Expressions.alwaysTrue())
+                .conflictDetectionFilter(Expressions.alwaysTrue());
+        if (baseSnapshotId != null) {
+            overwriteFiles = 
overwriteFiles.validateFromSnapshot(baseSnapshotId);
+        }
+        overwriteFiles = 
overwriteFiles.validateNoConflictingData().validateNoConflictingDeletes();
+        for (WriteResult result : pendingResults) {
+            Preconditions.checkState(result.referencedDataFiles().length == 0,
+                    "Should have no referenced data files for a whole-table 
overwrite.");
+            Arrays.stream(result.dataFiles()).forEach(overwriteFiles::addFile);
+        }
+        overwriteFiles.commit();
+        hasStagedUpdates = true;
+    }
+
     private void commitReplaceTxn(List<WriteResult> pendingResults) {
         if (pendingResults.isEmpty()) {
             // such as : insert overwrite table `dst_tb` select * from 
`empty_tb`
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutor.java
index 59b0fdd8e4f..5130e2f0180 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutor.java
@@ -54,7 +54,8 @@ public class IcebergInsertExecutor extends 
BaseExternalTableInsertExecutor {
     @Override
     protected void beforeExec() throws UserException {
         IcebergTransaction transaction = (IcebergTransaction) 
transactionManager.getTransaction(txnId);
-        transaction.beginInsert((IcebergExternalTable) table, 
targetIcebergTable, insertCtx);
+        transaction.beginInsert((IcebergExternalTable) table, 
targetIcebergTable, insertCtx,
+                ctx.getSessionVariable().getIcebergPartitionOverwriteMode());
     }
 
     @Override
@@ -75,10 +76,12 @@ public class IcebergInsertExecutor extends 
BaseExternalTableInsertExecutor {
 
     @Override
     public boolean shouldExecuteEmptyInsert() {
+        // An overwrite still has side effects with no source rows. The 
transaction decides whether
+        // to clear the whole table, delete explicit partitions, or preserve a 
partitioned dynamic table.
         return emptyInsert
                 && 
insertCtx.filter(IcebergInsertCommandContext.class::isInstance)
                         .map(IcebergInsertCommandContext.class::cast)
-                        
.map(IcebergInsertCommandContext::isStaticPartitionOverwrite)
+                        .map(IcebergInsertCommandContext::isOverwrite)
                         .orElse(false);
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 0c21e481a86..ff315d8674f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -4003,6 +4003,19 @@ public class SessionVariable implements Serializable, 
Writable {
                     "Enable merge partitioning for Iceberg UPDATE/DELETE 
(INSERT by partition columns, "
                             + "DELETE by row_id)."})
     public boolean enableIcebergMergePartitioning = true;
+
+    public static final String ICEBERG_PARTITION_OVERWRITE_MODE = 
"iceberg_partition_overwrite_mode";
+    public static final String ICEBERG_PARTITION_OVERWRITE_MODE_DYNAMIC = 
"dynamic";
+    public static final String ICEBERG_PARTITION_OVERWRITE_MODE_STATIC = 
"static";
+    @VariableMgr.VarAttr(name = ICEBERG_PARTITION_OVERWRITE_MODE, needForward 
= true,
+            checker = "checkIcebergPartitionOverwriteMode", setter = 
"setIcebergPartitionOverwriteMode",
+            description = {"Scope of INSERT OVERWRITE on an Iceberg table when 
no PARTITION clause is given. "
+                    + "'static' (default, matching Spark's 
partitionOverwriteMode=static) overwrites the whole "
+                    + "table, including data written under older partition 
specs. 'dynamic' replaces only "
+                    + "the partitions the new data lands in, preserving the 
previous Doris behavior."},
+            options = {ICEBERG_PARTITION_OVERWRITE_MODE_STATIC, 
ICEBERG_PARTITION_OVERWRITE_MODE_DYNAMIC})
+    public String icebergPartitionOverwriteMode = 
ICEBERG_PARTITION_OVERWRITE_MODE_STATIC;
+
     // If this fe is in fuzzy mode, then will use initFuzzyModeVariables to 
generate some variables,
     // not the default value set in the code.
 
@@ -5714,6 +5727,30 @@ public class SessionVariable implements Serializable, 
Writable {
         parseInsertVisibleTimeoutReturnMode(mode);
     }
 
+    public String getIcebergPartitionOverwriteMode() {
+        return icebergPartitionOverwriteMode;
+    }
+
+    public void checkIcebergPartitionOverwriteMode(String mode) {
+        parseIcebergPartitionOverwriteMode(mode);
+    }
+
+    public void setIcebergPartitionOverwriteMode(String mode) {
+        icebergPartitionOverwriteMode = 
parseIcebergPartitionOverwriteMode(mode);
+    }
+
+    private static String parseIcebergPartitionOverwriteMode(String mode) {
+        if (mode != null) {
+            String normalized = mode.trim().toLowerCase(Locale.ROOT);
+            if (ICEBERG_PARTITION_OVERWRITE_MODE_DYNAMIC.equals(normalized)
+                    || 
ICEBERG_PARTITION_OVERWRITE_MODE_STATIC.equals(normalized)) {
+                return normalized;
+            }
+        }
+        throw new UnsupportedOperationException(
+                "iceberg_partition_overwrite_mode must be 'dynamic' or 
'static', but was: " + mode);
+    }
+
     // Parse the stored string case-insensitively and expose the enum only to 
business logic.
     private InsertVisibleTimeoutReturnMode 
parseInsertVisibleTimeoutReturnMode(String mode) {
         if (StringUtils.isEmpty(mode)) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergTransactionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergTransactionTest.java
index 73765a64927..0bf0ce98424 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergTransactionTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergTransactionTest.java
@@ -46,6 +46,7 @@ import org.apache.iceberg.RowDelta;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.SortOrder;
 import org.apache.iceberg.Table;
+import org.apache.iceberg.TableScan;
 import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.catalog.TableIdentifier;
 import org.apache.iceberg.exceptions.CommitFailedException;
@@ -576,7 +577,7 @@ public class IcebergTransactionTest {
         try (MockedStatic<IcebergUtils> mockedUtils =
                 Mockito.mockStatic(IcebergUtils.class, 
Mockito.CALLS_REAL_METHODS)) {
             mockWritableTable(mockedUtils, table);
-            txn.beginInsert(dorisTable, Optional.of(insertContext));
+            txn.beginInsert(dorisTable, table, Optional.of(insertContext), 
"dynamic");
             if (hasOutputFile) {
                 txn.finishInsert(NameMapping.createForTest(dbName, tableName));
             }
@@ -854,6 +855,124 @@ public class IcebergTransactionTest {
         Assert.assertEquals("2024-12-11", numToDay(dt));
     }
 
+    @Test
+    public void testPartitionOverwriteModes() throws Exception {
+        for (String mode : new String[] {null, "static", "dynamic"}) {
+            verifyPartitionOverwriteMode(mode, false, false, false);
+            verifyPartitionOverwriteMode(mode, true, false, false);
+        }
+    }
+
+    @Test
+    public void testWholeTableOverwriteClearsOlderPartitionSpecs() throws 
Exception {
+        verifyPartitionOverwriteMode("static", false, true, false);
+        verifyPartitionOverwriteMode("static", true, true, false);
+    }
+
+    @Test
+    public void testWholeTableOverwriteTargetsOnlyBranch() throws Exception {
+        verifyPartitionOverwriteMode("static", false, false, true);
+        verifyPartitionOverwriteMode("static", true, false, true);
+    }
+
+    private void verifyPartitionOverwriteMode(String mode, boolean emptySource,
+            boolean evolveSpec, boolean targetBranch) throws Exception {
+        String tableName = "overwrite_" + 
UUID.randomUUID().toString().replace("-", "");
+        Schema schema = new Schema(Types.NestedField.required(1, "id", 
Types.IntegerType.get()),
+                Types.NestedField.required(2, "p", Types.StringType.get()));
+        PartitionSpec spec = evolveSpec ? PartitionSpec.unpartitioned()
+                : PartitionSpec.builderFor(schema).identity("p").build();
+        Table table = ops.getCatalog().createTable(TableIdentifier.of(dbName, 
tableName), schema, spec);
+        DataFile seed = DataFiles.builder(spec).withPath(table.location() + 
"/seed.parquet")
+                .withPartitionPath(evolveSpec ? "" : 
"p=us").withFileSizeInBytes(1).withRecordCount(1).build();
+        table.newAppend().appendFile(seed).commit();
+        if (evolveSpec) {
+            table.updateSpec().addField("p").commit();
+        }
+        IcebergInsertCommandContext context = new 
IcebergInsertCommandContext();
+        context.setOverwrite(true);
+        if (targetBranch) {
+            table.manageSnapshots().createBranch("audit").commit();
+            context.setBranchName(Optional.of("audit"));
+            // Main advances independently, so the conflict base must be the 
audit branch's head.
+            table.newAppend().appendFile(DataFiles.builder(table.spec())
+                    .withPath(table.location() + 
"/main.parquet").withPartitionPath("p=ap")
+                    
.withFileSizeInBytes(1).withRecordCount(1).build()).commit();
+        }
+        IcebergExternalTable dorisTable = 
Mockito.mock(IcebergExternalTable.class);
+        Mockito.when(dorisTable.getName()).thenReturn(tableName);
+        try (MockedStatic<IcebergUtils> mockedUtils =
+                Mockito.mockStatic(IcebergUtils.class, 
Mockito.CALLS_REAL_METHODS)) {
+            mockWritableTable(mockedUtils, table);
+            IcebergTransaction txn = getTxn();
+            if (mode == null) {
+                txn.beginInsert(dorisTable, table, Optional.of(context));
+            } else {
+                txn.beginInsert(dorisTable, table, Optional.of(context), mode);
+            }
+            if (!emptySource) {
+                TIcebergCommitData data = new TIcebergCommitData();
+                data.setFilePath(table.location() + "/output.parquet");
+                data.setPartitionValues(Collections.singletonList("eu"));
+                data.setPartitionSpecId(table.spec().specId());
+                data.setFileContent(TFileContent.DATA);
+                data.setRowCount(1);
+                data.setFileSize(1);
+                txn.updateIcebergCommitData(Collections.singletonList(data));
+            }
+            txn.finishInsert(NameMapping.createForTest(dbName, tableName));
+            txn.commit();
+        }
+        table.refresh();
+        TableScan scan = targetBranch ? table.newScan().useRef("audit") : 
table.newScan();
+        List<String> files = new ArrayList<>();
+        try (CloseableIterable<FileScanTask> tasks = scan.planFiles()) {
+            tasks.forEach(task -> files.add(task.file().path().toString()));
+        }
+        Assert.assertEquals(("dynamic".equals(mode) ? 1 : 0) + (emptySource ? 
0 : 1), files.size());
+        Assert.assertEquals("dynamic".equals(mode), 
files.contains(seed.path().toString()));
+        if (!emptySource) {
+            Assert.assertTrue(files.contains(table.location() + 
"/output.parquet"));
+        }
+        if (targetBranch) {
+            checkPushDownByPartition(table, Expressions.alwaysTrue(), 2);
+        }
+    }
+
+    @Test
+    public void testWholeTableOverwriteRejectsConcurrentDataAndDeletes() 
throws Exception {
+        for (boolean concurrentDelete : new boolean[] {false, true}) {
+            String tableName = "overwrite_conflict_" + concurrentDelete;
+            Schema schema = new Schema(Types.NestedField.required(1, "id", 
Types.IntegerType.get()));
+            Table table = 
ops.getCatalog().createTable(TableIdentifier.of(dbName, tableName), schema,
+                    PartitionSpec.unpartitioned(), 
ImmutableMap.of("format-version", "2"));
+            table.newAppend().appendFile(DataFiles.builder(table.spec())
+                    .withPath(table.location() + 
"/seed.parquet").withFileSizeInBytes(1)
+                    .withRecordCount(1).build()).commit();
+            IcebergExternalTable dorisTable = 
Mockito.mock(IcebergExternalTable.class);
+            Mockito.when(dorisTable.getName()).thenReturn(tableName);
+            IcebergInsertCommandContext context = new 
IcebergInsertCommandContext();
+            context.setOverwrite(true);
+            try (MockedStatic<IcebergUtils> mockedUtils =
+                    Mockito.mockStatic(IcebergUtils.class, 
Mockito.CALLS_REAL_METHODS)) {
+                mockWritableTable(mockedUtils, table);
+                IcebergTransaction txn = getTxn();
+                txn.beginInsert(dorisTable, table, Optional.of(context));
+                txn.finishInsert(NameMapping.createForTest(dbName, tableName));
+                if (concurrentDelete) {
+                    
table.newRowDelta().addDeletes(FileMetadata.deleteFileBuilder(table.spec())
+                            .ofEqualityDeletes(1).withPath(table.location() + 
"/delete.parquet")
+                            
.withFileSizeInBytes(1).withRecordCount(1).build()).commit();
+                } else {
+                    
table.newAppend().appendFile(DataFiles.builder(table.spec())
+                            .withPath(table.location() + 
"/concurrent.parquet").withFileSizeInBytes(1)
+                            .withRecordCount(1).build()).commit();
+                }
+                
Assert.assertThrows(org.apache.iceberg.exceptions.ValidationException.class, 
txn::commit);
+            }
+        }
+    }
+
     @Test
     public void testUnPartitionedTableOverwriteWithData() throws UserException 
{
 
@@ -904,7 +1023,15 @@ public class IcebergTransactionTest {
 
     @Test
     public void testUnpartitionedTableOverwriteWithoutData() throws 
UserException {
+        verifyUnpartitionedEmptyOverwrite("static");
+    }
 
+    @Test
+    public void testUnpartitionedDynamicOverwriteWithoutData() throws 
UserException {
+        verifyUnpartitionedEmptyOverwrite("dynamic");
+    }
+
+    private void verifyUnpartitionedEmptyOverwrite(String mode) throws 
UserException {
         testUnPartitionedTableOverwriteWithData();
 
         Table table = ops.getCatalog().loadTable(TableIdentifier.of(dbName, 
tbWithoutPartition));
@@ -917,7 +1044,7 @@ public class IcebergTransactionTest {
 
             IcebergTransaction txn = getTxn();
             IcebergInsertCommandContext ctx = new 
IcebergInsertCommandContext();
-            txn.beginInsert(icebergExternalTable, table, Optional.of(ctx));
+            txn.beginInsert(icebergExternalTable, table, Optional.of(ctx), 
mode);
             ctx.setOverwrite(true);
             txn.finishInsert(NameMapping.createForTest(dbName, 
tbWithPartition));
             txn.commit();
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutorTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutorTest.java
new file mode 100644
index 00000000000..4516a5fc849
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/IcebergInsertExecutorTest.java
@@ -0,0 +1,83 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.plans.commands.insert;
+
+import org.apache.doris.catalog.EnvFactory;
+import org.apache.doris.datasource.ExternalDatabase;
+import org.apache.doris.datasource.iceberg.IcebergExternalCatalog;
+import org.apache.doris.datasource.iceberg.IcebergExternalTable;
+import org.apache.doris.datasource.iceberg.IcebergTransaction;
+import org.apache.doris.nereids.NereidsPlanner;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.Coordinator;
+import org.apache.doris.transaction.TransactionManager;
+
+import org.apache.iceberg.Table;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.Optional;
+
+class IcebergInsertExecutorTest {
+    @AfterEach
+    void tearDown() {
+        ConnectContext.remove();
+    }
+
+    @Test
+    void testEmptyOverwriteExecutesAndPassesSessionMode() throws Exception {
+        ConnectContext ctx = new ConnectContext();
+        ctx.setThreadLocalInfo();
+        IcebergExternalCatalog catalog = 
Mockito.mock(IcebergExternalCatalog.class);
+        IcebergExternalTable table = Mockito.mock(IcebergExternalTable.class);
+        Mockito.when(table.getCatalog()).thenReturn(catalog);
+        
Mockito.when(table.getDatabase()).thenReturn(Mockito.mock(ExternalDatabase.class));
+        TransactionManager manager = Mockito.mock(TransactionManager.class);
+        Mockito.when(catalog.getTransactionManager()).thenReturn(manager);
+        IcebergTransaction transaction = 
Mockito.mock(IcebergTransaction.class);
+        
Mockito.when(manager.getTransaction(Mockito.anyLong())).thenReturn(transaction);
+        Table targetTable = Mockito.mock(Table.class);
+        EnvFactory factory = Mockito.mock(EnvFactory.class);
+        Mockito.when(factory.createCoordinator(Mockito.any(), Mockito.any(), 
Mockito.any(), Mockito.anyLong()))
+                .thenReturn(Mockito.mock(Coordinator.class));
+        try (MockedStatic<EnvFactory> mockedFactory = 
Mockito.mockStatic(EnvFactory.class)) {
+            mockedFactory.when(EnvFactory::getInstance).thenReturn(factory);
+            IcebergInsertCommandContext context = new 
IcebergInsertCommandContext();
+            context.setOverwrite(true);
+            for (String mode : new String[] {"static", "dynamic"}) {
+                
ctx.getSessionVariable().setIcebergPartitionOverwriteMode(mode);
+                IcebergInsertExecutor executor = new 
IcebergInsertExecutor(ctx, table, targetTable,
+                        "empty_overwrite", Mockito.mock(NereidsPlanner.class), 
Optional.of(context), true, 0L);
+                Assertions.assertTrue(executor.shouldExecuteEmptyInsert());
+                executor.beforeExec();
+                Mockito.verify(transaction).beginInsert(table, targetTable, 
Optional.of(context), mode);
+            }
+            context.setOverwrite(false);
+            IcebergInsertExecutor append = new IcebergInsertExecutor(ctx, 
table, targetTable,
+                    "empty_append", Mockito.mock(NereidsPlanner.class), 
Optional.of(context), true, 0L);
+            Assertions.assertFalse(append.shouldExecuteEmptyInsert());
+            context.setOverwrite(true);
+            IcebergInsertExecutor nonEmpty = new IcebergInsertExecutor(ctx, 
table, targetTable,
+                    "non_empty", Mockito.mock(NereidsPlanner.class), 
Optional.of(context), false, 0L);
+            Assertions.assertFalse(nonEmpty.shouldExecuteEmptyInsert());
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
index dc984606dcb..1ec21e7e961 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
@@ -248,6 +248,42 @@ public class SessionVariablesTest extends 
TestWithFeService {
         Assertions.assertEquals(Action.NOPUSH, 
restored.getForceEagerAggHintMap().get("sum:t2.b"));
     }
 
+    @Test
+    public void testIcebergPartitionOverwriteMode() throws Exception {
+        SessionVariable sessionVar = new SessionVariable();
+        Assertions.assertEquals("static", 
sessionVar.getIcebergPartitionOverwriteMode());
+        VariableMgr.setVar(sessionVar, new SetVar(SetType.SESSION,
+                SessionVariable.ICEBERG_PARTITION_OVERWRITE_MODE, new 
StringLiteral(" DyNaMiC ")));
+        Assertions.assertEquals("dynamic", 
sessionVar.getIcebergPartitionOverwriteMode());
+        Assertions.assertEquals("dynamic",
+                
sessionVar.getForwardVariables().get(SessionVariable.ICEBERG_PARTITION_OVERWRITE_MODE));
+        SessionVariable forwarded = new SessionVariable();
+        
forwarded.setForwardedSessionVariables(sessionVar.getForwardVariables());
+        Assertions.assertEquals("dynamic", 
forwarded.getIcebergPartitionOverwriteMode());
+        sessionVar.setIcebergPartitionOverwriteMode("StAtIc");
+        Assertions.assertEquals("static", 
sessionVar.getIcebergPartitionOverwriteMode());
+        for (String invalid : new String[] {null, "", "replace"}) {
+            Assertions.assertThrows(UnsupportedOperationException.class,
+                    () -> 
sessionVar.checkIcebergPartitionOverwriteMode(invalid));
+        }
+        ExceptionChecker.expectThrowsWithMsg(DdlException.class,
+                "iceberg_partition_overwrite_mode must be 'dynamic' or 
'static'",
+                () -> VariableMgr.setVar(sessionVar, new 
SetVar(SetType.SESSION,
+                        SessionVariable.ICEBERG_PARTITION_OVERWRITE_MODE, new 
StringLiteral("replace"))));
+    }
+
+    @Test
+    public void testIcebergPartitionOverwriteModeInHint() {
+        connectContext.setThreadLocalInfo();
+        new NereidsParser().parseSQL("select /*+ 
set_var(iceberg_partition_overwrite_mode='DyNaMiC') */ "
+                + "* from test_t1");
+        Assertions.assertEquals("dynamic", 
connectContext.getSessionVariable().getIcebergPartitionOverwriteMode());
+        RuntimeException exception = 
Assertions.assertThrows(RuntimeException.class,
+                () -> new NereidsParser().parseSQL(
+                        "select /*+ 
set_var(iceberg_partition_overwrite_mode='replace') */ * from test_t1"));
+        
Assertions.assertTrue(exception.getMessage().contains("iceberg_partition_overwrite_mode"));
+    }
+
     @Test
     public void testSetVarInHint() {
         String sql = "insert into test_t1 select /*+ 
set_var(enable_nereids_dml_with_pipeline=false)*/ * from test_t1 where 
enable_nereids_dml_with_pipeline=true";
diff --git 
a/regression-test/data/external_table_p0/iceberg/write/test_iceberg_partition_overwrite_mode.out
 
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_partition_overwrite_mode.out
new file mode 100644
index 00000000000..60587a9e8ae
--- /dev/null
+++ 
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_partition_overwrite_mode.out
@@ -0,0 +1,22 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !before --
+1      1
+1      2
+1      3
+
+-- !default_static_data --
+7      3
+
+-- !default_static_empty --
+
+-- !dynamic_data --
+1      1
+1      3
+9      2
+
+-- !dynamic_empty --
+1      1
+1      3
+9      2
+
+-- !static_optimized_empty --
diff --git 
a/regression-test/suites/external_table_p0/iceberg/iceberg_branch_insert_data.groovy
 
b/regression-test/suites/external_table_p0/iceberg/iceberg_branch_insert_data.groovy
index 68146796d0a..b1088fca73a 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/iceberg_branch_insert_data.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/iceberg_branch_insert_data.groovy
@@ -22,6 +22,9 @@ suite("iceberg_branch_insert_data", 
"p0,external,doris,external_docker,external_
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String rest_port = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minio_port = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/test_iceberg_jdbc_catalog.groovy
 
b/regression-test/suites/external_table_p0/iceberg/test_iceberg_jdbc_catalog.groovy
index 368fccc008b..d7db63d301b 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/test_iceberg_jdbc_catalog.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/test_iceberg_jdbc_catalog.groovy
@@ -22,6 +22,9 @@ suite("test_iceberg_jdbc_catalog", 
"p0,external,iceberg,external_docker,external
         return;
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String enabledJdbc = context.config.otherConfigs.get("enableJdbcTest")
     if (enabledJdbc == null || !enabledJdbc.equalsIgnoreCase("true")) {
         logger.info("Iceberg JDBC catalog test requires enableJdbcTest, skip 
this test")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/test_iceberg_timestamp_ns.groovy
 
b/regression-test/suites/external_table_p0/iceberg/test_iceberg_timestamp_ns.groovy
index 5815bad6219..085de0036e5 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/test_iceberg_timestamp_ns.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/test_iceberg_timestamp_ns.groovy
@@ -19,6 +19,9 @@ suite("test_iceberg_timestamp_ns", "p0,external,iceberg") {
     if 
(!context.config.otherConfigs.get("enableIcebergTest")?.equalsIgnoreCase("true"))
 {
         return
     }
+
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
     String host = context.config.otherConfigs.get("externalEnvIp")
     // Use the existing HDFS fixture so metadata defaults are not rescaled by 
the older REST server.
     String hdfsPort = context.config.otherConfigs.get("hive2HdfsPort")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy
index ce2415f9634..2e37dfc1e2b 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy
@@ -16,6 +16,9 @@
 // under the License.
 
 suite("test_iceberg_insert_overwrite", 
"p0,external,iceberg,external_docker,external_docker_iceberg") {
+
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
     def format_compressions = ["parquet_zstd", "orc_zlib"]
 
     def q01 = { String format_compression, String catalog_name ->
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite_with_empty_table.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite_with_empty_table.groovy
index 625a836ff30..00b90457fcc 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite_with_empty_table.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite_with_empty_table.groovy
@@ -22,6 +22,9 @@ suite("test_iceberg_insert_overwrite_with_empty_table", 
"p0,external,doris,exter
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String rest_port = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minio_port = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_partition_overwrite_mode.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_partition_overwrite_mode.groovy
new file mode 100644
index 00000000000..0f9f9a7f3bb
--- /dev/null
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_partition_overwrite_mode.groovy
@@ -0,0 +1,94 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_iceberg_partition_overwrite_mode",
+        "p0,external,iceberg,external_docker,external_docker_iceberg") {
+    String enabled = context.config.otherConfigs.get("enableIcebergTest")
+    if (enabled == null || !enabled.equalsIgnoreCase("true")) {
+        logger.info("disable iceberg test.")
+        return
+    }
+
+    String rest_port = context.config.otherConfigs.get("iceberg_rest_uri_port")
+    String minio_port = context.config.otherConfigs.get("iceberg_minio_port")
+    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+    String catalog_name = "test_iceberg_partition_overwrite_mode"
+
+    sql """drop catalog if exists ${catalog_name}"""
+    sql """
+    CREATE CATALOG ${catalog_name} PROPERTIES (
+        'type'='iceberg',
+        'iceberg.catalog.type'='rest',
+        'uri' = 'http://${externalEnvIp}:${rest_port}',
+        "s3.access_key" = "admin",
+        "s3.secret_key" = "password",
+        "s3.endpoint" = "http://${externalEnvIp}:${minio_port}";,
+        "s3.region" = "us-east-1"
+    );"""
+
+    sql """ switch ${catalog_name} """
+
+    String db1 = catalog_name + "_db1"
+    String tb1 = db1 + "_tb1"
+    String tb_empty = db1 + "_tb_empty"
+
+    sql """ drop database if exists ${db1} force"""
+    sql """ create database ${db1} """
+    sql """ create table ${db1}.${tb1} (id int, val int) partition by list 
(val)() """
+    sql """ create table ${db1}.${tb_empty} (id int, val int) """
+
+    sql """ use ${db1} """
+    sql """ insert into ${tb1} values (1,1), (1,2), (1,3) """
+
+    order_qt_before """ select * from ${tb1} order by val """
+
+    // The default (no SET) is static, matching Spark's default 
partitionOverwriteMode=static: a bare
+    // INSERT OVERWRITE clears the whole table first, so only the written row 
survives.
+    sql """ insert overwrite table ${tb1} values (7,3) """
+
+    order_qt_default_static_data """ select * from ${tb1} order by val """
+
+    // ... and an empty source empties the table, even though it is 
partitioned.
+    sql """ insert overwrite table ${tb1} select * from ${tb_empty} """
+
+    order_qt_default_static_empty """ select * from ${tb1} order by val """
+
+    // dynamic (Hive-compatible, Spark's partitionOverwriteMode=dynamic): only 
the written partition (val=2)
+    // is replaced, the others survive.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+    sql """ insert into ${tb1} values (1,1), (1,2), (1,3) """
+    sql """ insert overwrite table ${tb1} values (9,2) """
+
+    order_qt_dynamic_data """ select * from ${tb1} order by val """
+
+    // ... and an empty source is a no-op for a partitioned table.
+    sql """ insert overwrite table ${tb1} select * from ${tb_empty} """
+
+    order_qt_dynamic_empty """ select * from ${tb1} order by val """
+
+    // A planner-proven empty source (WHERE FALSE) must still clear the table 
in static mode. With strict DML
+    // consistency disabled (the cloud default) the empty relation reaches the 
sink directly, so the insert
+    // must still run its transaction instead of taking the empty-insert 
shortcut.
+    sql """ set enable_strict_consistency_dml = false """
+    sql """ set iceberg_partition_overwrite_mode = 'static' """
+    sql """ insert into ${tb1} values (1,1), (1,2), (1,3) """
+    sql """ insert overwrite table ${tb1} select * from ${tb1} where false """
+
+    order_qt_static_optimized_empty """ select * from ${tb1} order by val """
+
+    sql """ set enable_strict_consistency_dml = true """
+}
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_branch_dml_boundary.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_branch_dml_boundary.groovy
index f5f8ef5bb9c..28cf859f65d 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_branch_dml_boundary.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_branch_dml_boundary.groovy
@@ -23,6 +23,9 @@ suite("test_iceberg_write_branch_dml_boundary",
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String restPort = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minioPort = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_evolution_refs.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_evolution_refs.groovy
index 69fe59d2b72..fa8dc38ffb1 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_evolution_refs.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_evolution_refs.groovy
@@ -23,6 +23,9 @@ suite("test_iceberg_write_evolution_refs",
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String restPort = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minioPort = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_atomicity.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_atomicity.groovy
index fe6d8f2cc37..14ca8dd4587 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_atomicity.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_atomicity.groovy
@@ -23,6 +23,9 @@ suite("test_iceberg_write_overwrite_atomicity",
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String restPort = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minioPort = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_delete_files.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_delete_files.groovy
index d787962094a..6877e54610c 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_delete_files.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_delete_files.groovy
@@ -23,6 +23,9 @@ suite("test_iceberg_write_overwrite_delete_files",
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String restPort = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minioPort = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_evolution.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_evolution.groovy
index 07fa302ba52..b642e53f900 100644
--- 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_evolution.groovy
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_overwrite_evolution.groovy
@@ -23,6 +23,9 @@ suite("test_iceberg_write_overwrite_evolution",
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String restPort = context.config.otherConfigs.get("iceberg_rest_uri_port")
     String minioPort = context.config.otherConfigs.get("iceberg_minio_port")
     String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
diff --git 
a/regression-test/suites/external_table_p2/iceberg/test_s3tables_glue_insert_overwrite.groovy
 
b/regression-test/suites/external_table_p2/iceberg/test_s3tables_glue_insert_overwrite.groovy
index 4fa8d1e0291..6c77331a7e3 100644
--- 
a/regression-test/suites/external_table_p2/iceberg/test_s3tables_glue_insert_overwrite.groovy
+++ 
b/regression-test/suites/external_table_p2/iceberg/test_s3tables_glue_insert_overwrite.groovy
@@ -18,6 +18,9 @@
 import java.util.concurrent.ThreadLocalRandom
 
 suite("test_s3tables_glue_insert_overwrite", 
"p0,external,iceberg,external_docker,external_docker_iceberg") {
+
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
     def format_compressions = ["parquet_zstd", "orc_zlib"]
 
     def q01 = { String format_compression, String catalog_name ->
diff --git 
a/regression-test/suites/external_table_p2/iceberg/test_s3tables_insert_overwrite.groovy
 
b/regression-test/suites/external_table_p2/iceberg/test_s3tables_insert_overwrite.groovy
index 32d95fb2f04..c7738340723 100644
--- 
a/regression-test/suites/external_table_p2/iceberg/test_s3tables_insert_overwrite.groovy
+++ 
b/regression-test/suites/external_table_p2/iceberg/test_s3tables_insert_overwrite.groovy
@@ -631,6 +631,9 @@ suite("test_s3tables_insert_overwrite", 
"p0,external,iceberg,external_docker,ext
         return
     }
 
+    // Preserve this suite's dynamic overwrite expectations after the default 
changes to static.
+    sql """ set iceberg_partition_overwrite_mode = 'dynamic' """
+
     String catalog_name = "test_s3tables_insert_overwrite"
     String props = context.config.otherConfigs.get("icebergS3TablesCatalog")
     sql """drop catalog if exists ${catalog_name};"""


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to