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

jerryshao pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.3 by this push:
     new e6184a5eb4 [#11829] fix(doris): support replication allocation 
property (#12556)
e6184a5eb4 is described below

commit e6184a5eb43adb315b93224f2bb32cff53b5b266
Author: hutiefang76 <[email protected]>
AuthorDate: Mon Aug 24 13:58:47 2026 +0800

    [#11829] fix(doris): support replication allocation property (#12556)
    
    ### What changed
    
    Backports the merged main-branch fix from #11877 to branch-1.3. The JDBC
    Doris catalog now accepts the Doris 2.1+ replication_allocation property
    and avoids automatically adding replication_num=1 when that mutually
    exclusive property is already supplied.
    
    ### Scope
    
    This backport contains only the original property metadata, validation,
    SQL-generation, focused unit coverage, existing Doris integration
    coverage, and documentation changes.
    
    ### Verification
    
    - git diff --check
    - JDK 17: ./gradlew :catalogs:catalog-jdbc-doris:test --tests
    org.apache.gravitino.catalog.doris.TestDorisCatalog --tests
    
org.apache.gravitino.catalog.doris.operation.TestDorisTableOperationsSqlGeneration
    -PskipITs
    
    The Docker-backed integration test is retained in the patch and will be
    validated by project CI.
    
    Backport of #11877. Closes #11829
---
 .../doris/DorisTablePropertiesMetadata.java        |  7 +++
 .../doris/operation/DorisTableOperations.java      | 11 +++-
 .../gravitino/catalog/doris/TestDorisCatalog.java  | 12 ++++
 .../doris/integration/test/CatalogDorisIT.java     | 25 ++++++++
 .../TestDorisTableOperationsSqlGeneration.java     | 66 ++++++++++++++++++++++
 docs/jdbc-doris-catalog.md                         |  1 +
 6 files changed, 121 insertions(+), 1 deletion(-)

diff --git 
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/DorisTablePropertiesMetadata.java
 
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/DorisTablePropertiesMetadata.java
index 4cad4c0351..c19bf15e2b 100644
--- 
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/DorisTablePropertiesMetadata.java
+++ 
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/DorisTablePropertiesMetadata.java
@@ -28,6 +28,7 @@ import org.apache.gravitino.connector.PropertyEntry;
 public class DorisTablePropertiesMetadata extends JdbcTablePropertiesMetadata {
 
   public static final String REPLICATION_FACTOR = "replication_num";
+  public static final String REPLICATION_ALLOCATION = "replication_allocation";
   public static final int DEFAULT_REPLICATION_FACTOR = 1;
   public static final int DEFAULT_REPLICATION_FACTOR_IN_SERVER_SIDE = 3;
 
@@ -42,6 +43,12 @@ public class DorisTablePropertiesMetadata extends 
JdbcTablePropertiesMetadata {
                     + " the default value will be used",
                 false /* immutable */,
                 DEFAULT_REPLICATION_FACTOR, /* default value */
+                false /* hidden */),
+            PropertyEntry.stringOptionalPropertyEntry(
+                REPLICATION_ALLOCATION,
+                "The replication allocation policy for the table.",
+                false /* immutable */,
+                null /* default value */,
                 false /* hidden */));
 
     PROPERTIES_METADATA = Maps.uniqueIndex(propertyEntries, 
PropertyEntry::getName);
diff --git 
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
 
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
index 926c193267..657dc04c12 100644
--- 
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
+++ 
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
@@ -20,6 +20,7 @@ package org.apache.gravitino.catalog.doris.operation;
 
 import static 
org.apache.gravitino.catalog.doris.DorisCatalog.DORIS_TABLE_PROPERTIES_META;
 import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.DEFAULT_REPLICATION_FACTOR_IN_SERVER_SIDE;
+import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_ALLOCATION;
 import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_FACTOR;
 import static 
org.apache.gravitino.catalog.doris.utils.DorisUtils.generatePartitionSqlFragment;
 import static 
org.apache.gravitino.catalog.jdbc.utils.JdbcConnectorUtils.escapeSqlLiteral;
@@ -179,9 +180,17 @@ public class DorisTableOperations extends 
JdbcTableOperations {
       resultMap = new HashMap<>(properties);
     }
 
+    Preconditions.checkArgument(
+        !resultMap.containsKey(REPLICATION_FACTOR)
+            || !resultMap.containsKey(REPLICATION_ALLOCATION),
+        "Properties '%s' and '%s' cannot be set at the same time",
+        REPLICATION_FACTOR,
+        REPLICATION_ALLOCATION);
+
     // If the backend server is less than 
DEFAULT_REPLICATION_FACTOR_IN_SERVER_SIDE (3), we need to
     // set the property 'replication_num' to 1 explicitly.
-    if (!resultMap.containsKey(REPLICATION_FACTOR)) {
+    if (!resultMap.containsKey(REPLICATION_FACTOR)
+        && !resultMap.containsKey(REPLICATION_ALLOCATION)) {
       // Try to check the number of backend servers using `show backends`, 
this SQL is supported by
       // all versions of Doris
       String query = "show backends";
diff --git 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/TestDorisCatalog.java
 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/TestDorisCatalog.java
index 039a15b0dc..b12e3cf095 100644
--- 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/TestDorisCatalog.java
+++ 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/TestDorisCatalog.java
@@ -19,6 +19,7 @@
 
 package org.apache.gravitino.catalog.doris;
 
+import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_ALLOCATION;
 import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_FACTOR;
 
 import java.util.Map;
@@ -33,6 +34,7 @@ public class TestDorisCatalog {
     DorisTablePropertiesMetadata dorisTablePropertiesMetadata = new 
DorisTablePropertiesMetadata();
     Map<String, PropertyEntry<?>> propertyEntryMap =
         dorisTablePropertiesMetadata.specificPropertyEntries();
+    Assertions.assertEquals(2, propertyEntryMap.size());
     Assertions.assertTrue(propertyEntryMap.containsKey(REPLICATION_FACTOR));
 
     PropertyEntry<?> propertyEntry = propertyEntryMap.get(REPLICATION_FACTOR);
@@ -41,5 +43,15 @@ public class TestDorisCatalog {
     Assertions.assertEquals(
         DorisTablePropertiesMetadata.DEFAULT_REPLICATION_FACTOR, 
propertyEntry.getDefaultValue());
     Assertions.assertFalse(propertyEntry.isHidden());
+
+    
Assertions.assertTrue(propertyEntryMap.containsKey(REPLICATION_ALLOCATION));
+    PropertyEntry<?> replicationAllocation = 
propertyEntryMap.get(REPLICATION_ALLOCATION);
+    Assertions.assertEquals(REPLICATION_ALLOCATION, 
replicationAllocation.getName());
+    Assertions.assertFalse(replicationAllocation.isRequired());
+    Assertions.assertFalse(replicationAllocation.isImmutable());
+    Assertions.assertFalse(replicationAllocation.isReserved());
+    Assertions.assertFalse(replicationAllocation.isHidden());
+    Assertions.assertEquals(String.class, replicationAllocation.getJavaType());
+    Assertions.assertNull(replicationAllocation.getDefaultValue());
   }
 }
diff --git 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDorisIT.java
 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDorisIT.java
index e474c10fa7..9d1a90f60b 100644
--- 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDorisIT.java
+++ 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDorisIT.java
@@ -18,6 +18,8 @@
  */
 package org.apache.gravitino.catalog.doris.integration.test;
 
+import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_ALLOCATION;
+import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_FACTOR;
 import static 
org.apache.gravitino.integration.test.util.ITUtils.assertPartition;
 import static 
org.apache.gravitino.rel.Column.DEFAULT_VALUE_OF_CURRENT_TIMESTAMP;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -380,6 +382,29 @@ public class CatalogDorisIT extends BaseIT {
         renamedTable);
   }
 
+  @Test
+  void testCreateTableWithReplicationAllocation() {
+    NameIdentifier tableIdentifier =
+        NameIdentifier.of(
+            schemaName, 
GravitinoITUtils.genRandomName("doris_replication_allocation"));
+    String replicationAllocation = "tag.location.default: 1";
+    Map<String, String> properties = ImmutableMap.of(REPLICATION_ALLOCATION, 
replicationAllocation);
+    TableCatalog tableCatalog = catalog.asTableCatalog();
+
+    tableCatalog.createTable(
+        tableIdentifier,
+        createColumns(),
+        table_comment,
+        properties,
+        Transforms.EMPTY_TRANSFORM,
+        createDistribution(),
+        null);
+
+    Table loadedTable = tableCatalog.loadTable(tableIdentifier);
+    assertEquals(replicationAllocation, 
loadedTable.properties().get(REPLICATION_ALLOCATION));
+    assertFalse(loadedTable.properties().containsKey(REPLICATION_FACTOR));
+  }
+
   @Test
   void testDorisIllegalTableName() {
     Map<String, String> properties = createTableProperties();
diff --git 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
index 68b442bbe9..ba7b665c01 100644
--- 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
+++ 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
@@ -18,11 +18,16 @@
  */
 package org.apache.gravitino.catalog.doris.operation;
 
+import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_ALLOCATION;
+import static 
org.apache.gravitino.catalog.doris.DorisTablePropertiesMetadata.REPLICATION_FACTOR;
+
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.Statement;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import javax.sql.DataSource;
 import org.apache.gravitino.catalog.doris.converter.DorisTypeConverter;
 import org.apache.gravitino.catalog.jdbc.JdbcColumn;
@@ -71,6 +76,10 @@ public class TestDorisTableOperationsSqlGeneration {
       }
     }
 
+    public void setDataSource(DataSource dataSource) {
+      super.dataSource = dataSource;
+    }
+
     public String createTableSql(
         String tableName, JdbcColumn[] columns, Distribution distribution) {
       return createTableSql(tableName, columns, distribution, "comment");
@@ -495,4 +504,61 @@ public class TestDorisTableOperationsSqlGeneration {
     Assertions.assertTrue(DorisTableOperations.isVersionAtLeast("2.1.1", 2, 1, 
0));
     Assertions.assertFalse(DorisTableOperations.isVersionAtLeast("2.1.0", 2, 
1, 1));
   }
+
+  @Test
+  public void 
testAppendNecessaryPropertiesAddsReplicationNumWhenBackendsAreNotEnough()
+      throws Exception {
+    TestableDorisTableOperations ops = new TestableDorisTableOperations();
+    ops.setDataSource(mockBackendDataSource(1));
+
+    Map<String, String> properties = 
ops.appendNecessaryProperties(Collections.emptyMap());
+
+    Assertions.assertEquals("1", properties.get(REPLICATION_FACTOR));
+  }
+
+  @Test
+  public void testAppendNecessaryPropertiesKeepsReplicationAllocation() throws 
Exception {
+    TestableDorisTableOperations ops = new TestableDorisTableOperations();
+    ops.setDataSource(mockBackendDataSource(1));
+
+    Map<String, String> properties = new HashMap<>();
+    properties.put(REPLICATION_ALLOCATION, "tag.location.default: 1");
+
+    Map<String, String> result = ops.appendNecessaryProperties(properties);
+
+    Assertions.assertEquals("tag.location.default: 1", 
result.get(REPLICATION_ALLOCATION));
+    Assertions.assertFalse(result.containsKey(REPLICATION_FACTOR));
+  }
+
+  @Test
+  public void 
testAppendNecessaryPropertiesRejectsConflictingReplicationProperties() {
+    TestableDorisTableOperations ops = new TestableDorisTableOperations();
+    Map<String, String> properties = new HashMap<>();
+    properties.put(REPLICATION_FACTOR, "1");
+    properties.put(REPLICATION_ALLOCATION, "tag.location.default: 1");
+
+    IllegalArgumentException exception =
+        Assertions.assertThrows(
+            IllegalArgumentException.class, () -> 
ops.appendNecessaryProperties(properties));
+
+    Assertions.assertEquals(
+        "Properties 'replication_num' and 'replication_allocation' cannot be 
set at the same time",
+        exception.getMessage());
+  }
+
+  private static DataSource mockBackendDataSource(int aliveBackendCount) 
throws Exception {
+    DataSource dataSource = Mockito.mock(DataSource.class);
+    Connection connection = Mockito.mock(Connection.class);
+    Statement statement = Mockito.mock(Statement.class);
+    ResultSet resultSet = Mockito.mock(ResultSet.class);
+
+    Mockito.when(dataSource.getConnection()).thenReturn(connection);
+    Mockito.when(connection.createStatement()).thenReturn(statement);
+    Mockito.when(statement.executeQuery("show 
backends")).thenReturn(resultSet);
+    int[] remainingAliveBackends = new int[] {aliveBackendCount};
+    Mockito.when(resultSet.next()).thenAnswer(invocation -> 
remainingAliveBackends[0]-- > 0);
+    Mockito.when(resultSet.getString("Alive")).thenReturn("true");
+
+    return dataSource;
+  }
 }
diff --git a/docs/jdbc-doris-catalog.md b/docs/jdbc-doris-catalog.md
index 43706917ac..f362d9c1fb 100644
--- a/docs/jdbc-doris-catalog.md
+++ b/docs/jdbc-doris-catalog.md
@@ -209,6 +209,7 @@ Index[] indexes = new Index[] {
 
 - Doris supports table properties, and you can set them in the table 
properties.
 - Only supports Doris table properties and doesn't support user-defined 
properties.
+- `replication_allocation` is supported for Doris 2.1 and later. Do not set it 
together with `replication_num`.
 
 ### Table Indexes
 

Reply via email to