This is an automated email from the ASF dual-hosted git repository.
yuqi1129 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new cf289fb759 [#11590] fix(doris): fix partition parsing for Doris 3.0+
format (#11732)
cf289fb759 is described below
commit cf289fb759c26cb8cde984cb98e35b9770f08ff4
Author: StormSpirit <[email protected]>
AuthorDate: Mon Jul 13 21:31:37 2026 +0800
[#11590] fix(doris): fix partition parsing for Doris 3.0+ format (#11732)
## What changes were proposed in this pull request?
### Partition Regex Fix (`DorisUtils.java`)
- Added `\\s*` to `PARTITION_INFO_PATTERN` to tolerate whitespace
between `LIST`/`RANGE` and `(` in Doris 3.0+ `SHOW CREATE TABLE` output
(`PARTITION BY LIST (` vs `PARTITION BY LIST(`)
### Integration Tests
- `CatalogDorisIT` (1.2.x): `testListPartitionRoundTrip` +
`testMultiColumnListPartitionRoundTrip`
- `CatalogDoris3xIT` (3.0.x): `testListPartitionRoundTrip` +
`testRangePartitionRoundTrip`
- `CatalogDoris4xIT` (4.0.x): `testListPartitionRoundTrip` +
`testRangePartitionRoundTrip`
All tests verify partition metadata survives the create → Doris → load
round-trip.
Fixed: #11590
## Does this PR introduce any user-facing change?
No. Partition parsing fix is internal to Gravitino metadata loading.
## How was this patch tested?
Unit tests: `TestDorisUtils` (existing, covers both LIST and RANGE
parsing)
Integration tests (Docker, all three Doris versions):
- `CatalogDorisIT` (1.2.x): 19/19 passed
- `CatalogDoris3xIT` (3.0.x): 8/8 passed
- `CatalogDoris4xIT` (4.0.x): 8/8 passed
---------
Signed-off-by: jiangxt2 <[email protected]>
---
.../gravitino/catalog/doris/utils/DorisUtils.java | 2 +-
.../doris/integration/test/CatalogDoris3xIT.java | 112 +++++++++++++++++++++
.../doris/integration/test/CatalogDoris4xIT.java | 111 ++++++++++++++++++++
.../doris/integration/test/CatalogDorisIT.java | 89 ++++++++++++++++
.../catalog/doris/utils/TestDorisUtils.java | 21 ++++
5 files changed, 334 insertions(+), 1 deletion(-)
diff --git
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/utils/DorisUtils.java
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/utils/DorisUtils.java
index 0a565bb6f6..03d4dd136e 100644
---
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/utils/DorisUtils.java
+++
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/utils/DorisUtils.java
@@ -45,7 +45,7 @@ import org.slf4j.LoggerFactory;
public final class DorisUtils {
private static final Logger LOGGER =
LoggerFactory.getLogger(DorisUtils.class);
private static final Pattern PARTITION_INFO_PATTERN =
- Pattern.compile("PARTITION BY \\b(LIST|RANGE)\\b\\((.+)\\)");
+ Pattern.compile("PARTITION BY \\b(LIST|RANGE)\\b\\s*\\((.+)\\)");
private static final Pattern DISTRIBUTION_INFO_PATTERN =
Pattern.compile(
diff --git
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris3xIT.java
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris3xIT.java
index d3f80abedf..712b5201d8 100644
---
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris3xIT.java
+++
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris3xIT.java
@@ -18,6 +18,7 @@
*/
package org.apache.gravitino.catalog.doris.integration.test;
+import static
org.apache.gravitino.integration.test.util.ITUtils.assertPartition;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -27,6 +28,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.gravitino.Catalog;
import org.apache.gravitino.NameIdentifier;
@@ -38,15 +40,23 @@ import
org.apache.gravitino.integration.test.container.DorisImageName;
import org.apache.gravitino.integration.test.util.BaseIT;
import org.apache.gravitino.integration.test.util.GravitinoITUtils;
import org.apache.gravitino.rel.Column;
+import org.apache.gravitino.rel.SupportsPartitions;
import org.apache.gravitino.rel.Table;
import org.apache.gravitino.rel.TableCatalog;
import org.apache.gravitino.rel.TableChange;
import org.apache.gravitino.rel.expressions.NamedReference;
import org.apache.gravitino.rel.expressions.distributions.Distribution;
import org.apache.gravitino.rel.expressions.distributions.Distributions;
+import org.apache.gravitino.rel.expressions.literals.Literal;
+import org.apache.gravitino.rel.expressions.literals.Literals;
+import org.apache.gravitino.rel.expressions.transforms.Transform;
import org.apache.gravitino.rel.expressions.transforms.Transforms;
import org.apache.gravitino.rel.indexes.Index;
import org.apache.gravitino.rel.indexes.Indexes;
+import org.apache.gravitino.rel.partitions.ListPartition;
+import org.apache.gravitino.rel.partitions.Partition;
+import org.apache.gravitino.rel.partitions.Partitions;
+import org.apache.gravitino.rel.partitions.RangePartition;
import org.apache.gravitino.rel.types.Types;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterAll;
@@ -315,6 +325,108 @@ public class CatalogDoris3xIT extends BaseIT {
assertEquals(Types.ExternalType.of("json"), findColumn(t,
"json_col").dataType());
}
+ @Test
+ void testListPartitionRoundTrip() {
+ // Verify LIST partition with assignments round-trips correctly on Doris
3.0.x.
+ // The partition parsing regex was updated to handle Doris 3.0+ format
with spaces.
+ TableCatalog tc = catalog.asTableCatalog();
+ NameIdentifier tid =
+ NameIdentifier.of(schemaName,
GravitinoITUtils.genRandomName("t_list_partition"));
+
+ Column cityCol = Column.of("city", Types.VarCharType.of(50), "city",
false, false, null);
+ Distribution dist = Distributions.hash(1, NamedReference.field("city"));
+
+ // Create table with initial partition assignments so Doris 3.0.x
recognizes it as partitioned.
+ Literal[][] p1Values = {{Literals.of("beijing",
Types.VarCharType.of(50))}};
+ Literal[][] p2Values = {{Literals.of("shanghai",
Types.VarCharType.of(50))}};
+ ListPartition p1 = Partitions.list("p1", p1Values, Collections.emptyMap());
+ ListPartition p2 = Partitions.list("p2", p2Values, Collections.emptyMap());
+ Transform[] partitioning = {
+ Transforms.list(new String[][] {{"city"}}, new ListPartition[] {p1, p2})
+ };
+
+ tc.createTable(
+ tid,
+ new Column[] {cityCol},
+ tableComment,
+ Collections.emptyMap(),
+ partitioning,
+ dist,
+ null,
+ null);
+
+ // Verify round-trip
+ Table loaded = tc.loadTable(tid);
+ assertEquals(1, loaded.partitioning().length);
+ assertEquals("list", loaded.partitioning()[0].name());
+
+ Map<String, ListPartition> partitions =
+ Arrays.stream(loaded.supportPartitions().listPartitions())
+ .collect(Collectors.toMap(Partition::name, p -> (ListPartition)
p));
+ assertEquals(2, partitions.size());
+ assertPartition(Partitions.list("p1", p1Values, Collections.emptyMap()),
partitions.get("p1"));
+ assertPartition(Partitions.list("p2", p2Values, Collections.emptyMap()),
partitions.get("p2"));
+ }
+
+ @Test
+ void testRangePartitionRoundTrip() {
+ // Verify RANGE partition round-trips correctly on Doris 3.0.x.
+ // The regex was updated to tolerate space between RANGE and parenthesis.
+ TableCatalog tc = catalog.asTableCatalog();
+ NameIdentifier tid =
+ NameIdentifier.of(schemaName,
GravitinoITUtils.genRandomName("t_range_partition"));
+
+ Column dateCol = Column.of("dt", Types.DateType.get(), "date", false,
false, null);
+ Distribution dist = Distributions.hash(1, NamedReference.field("dt"));
+
+ Literal todayLiteral = Literals.of("2024-07-24", Types.DateType.get());
+ Literal tomorrowLiteral = Literals.of("2024-07-25", Types.DateType.get());
+ RangePartition p1 = Partitions.range("p1", todayLiteral, Literals.NULL,
Collections.emptyMap());
+ RangePartition p2 =
+ Partitions.range("p2", tomorrowLiteral, todayLiteral,
Collections.emptyMap());
+ RangePartition p3 =
+ Partitions.range("p3", Literals.NULL, tomorrowLiteral,
Collections.emptyMap());
+ Transform[] partitioning = {
+ Transforms.range(new String[] {"dt"}, new RangePartition[] {p1, p2, p3})
+ };
+
+ tc.createTable(
+ tid,
+ new Column[] {dateCol},
+ tableComment,
+ Collections.emptyMap(),
+ partitioning,
+ dist,
+ null,
+ null);
+
+ Table loaded = tc.loadTable(tid);
+ assertEquals(1, loaded.partitioning().length);
+ assertEquals("range", loaded.partitioning()[0].name());
+
+ // Verify partition assignments
+ SupportsPartitions partitionOps = loaded.supportPartitions();
+ Map<String, RangePartition> partitions =
+ Arrays.stream(partitionOps.listPartitions())
+ .collect(Collectors.toMap(Partition::name, p -> (RangePartition)
p));
+ assertEquals(3, partitions.size());
+ assertPartition(
+ Partitions.range(
+ "p1",
+ todayLiteral,
+ Literals.of("0000-01-01", Types.DateType.get()),
+ Collections.emptyMap()),
+ partitions.get("p1"));
+ assertPartition(p2, partitions.get("p2"));
+ assertPartition(
+ Partitions.range(
+ "p3",
+ Literals.of("MAXVALUE", Types.DateType.get()),
+ tomorrowLiteral,
+ Collections.emptyMap()),
+ partitions.get("p3"));
+ }
+
private Column findColumn(Table table, String columnName) {
return Arrays.stream(table.columns())
.filter(c -> c.name().equals(columnName))
diff --git
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris4xIT.java
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris4xIT.java
index 9d64f5bbee..b6d1f67f7c 100644
---
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris4xIT.java
+++
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/integration/test/CatalogDoris4xIT.java
@@ -18,6 +18,7 @@
*/
package org.apache.gravitino.catalog.doris.integration.test;
+import static
org.apache.gravitino.integration.test.util.ITUtils.assertPartition;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -27,6 +28,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.gravitino.Catalog;
import org.apache.gravitino.NameIdentifier;
@@ -38,15 +40,23 @@ import
org.apache.gravitino.integration.test.container.DorisImageName;
import org.apache.gravitino.integration.test.util.BaseIT;
import org.apache.gravitino.integration.test.util.GravitinoITUtils;
import org.apache.gravitino.rel.Column;
+import org.apache.gravitino.rel.SupportsPartitions;
import org.apache.gravitino.rel.Table;
import org.apache.gravitino.rel.TableCatalog;
import org.apache.gravitino.rel.TableChange;
import org.apache.gravitino.rel.expressions.NamedReference;
import org.apache.gravitino.rel.expressions.distributions.Distribution;
import org.apache.gravitino.rel.expressions.distributions.Distributions;
+import org.apache.gravitino.rel.expressions.literals.Literal;
+import org.apache.gravitino.rel.expressions.literals.Literals;
+import org.apache.gravitino.rel.expressions.transforms.Transform;
import org.apache.gravitino.rel.expressions.transforms.Transforms;
import org.apache.gravitino.rel.indexes.Index;
import org.apache.gravitino.rel.indexes.Indexes;
+import org.apache.gravitino.rel.partitions.ListPartition;
+import org.apache.gravitino.rel.partitions.Partition;
+import org.apache.gravitino.rel.partitions.Partitions;
+import org.apache.gravitino.rel.partitions.RangePartition;
import org.apache.gravitino.rel.types.Types;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterAll;
@@ -315,6 +325,107 @@ public class CatalogDoris4xIT extends BaseIT {
assertEquals(Types.ExternalType.of("json"), findColumn(t,
"json_col").dataType());
}
+ @Test
+ void testListPartitionRoundTrip() {
+ // Verify LIST partition with assignments round-trips correctly on Doris
4.0.x.
+ // Doris 4.0.x uses the same SHOW CREATE TABLE format as 3.0.x for
partitions.
+ TableCatalog tc = catalog.asTableCatalog();
+ NameIdentifier tid =
+ NameIdentifier.of(schemaName,
GravitinoITUtils.genRandomName("t_list_partition"));
+
+ Column cityCol = Column.of("city", Types.VarCharType.of(50), "city",
false, false, null);
+ Distribution dist = Distributions.hash(1, NamedReference.field("city"));
+
+ // Create table with initial partition assignments so Doris 4.0.x
recognizes it as partitioned.
+ Literal[][] p1Values = {{Literals.of("beijing",
Types.VarCharType.of(50))}};
+ Literal[][] p2Values = {{Literals.of("shanghai",
Types.VarCharType.of(50))}};
+ ListPartition p1 = Partitions.list("p1", p1Values, Collections.emptyMap());
+ ListPartition p2 = Partitions.list("p2", p2Values, Collections.emptyMap());
+ Transform[] partitioning = {
+ Transforms.list(new String[][] {{"city"}}, new ListPartition[] {p1, p2})
+ };
+
+ tc.createTable(
+ tid,
+ new Column[] {cityCol},
+ tableComment,
+ Collections.emptyMap(),
+ partitioning,
+ dist,
+ null,
+ null);
+
+ // Verify round-trip
+ Table loaded = tc.loadTable(tid);
+ assertEquals(1, loaded.partitioning().length);
+ assertEquals("list", loaded.partitioning()[0].name());
+
+ Map<String, ListPartition> partitions =
+ Arrays.stream(loaded.supportPartitions().listPartitions())
+ .collect(Collectors.toMap(Partition::name, p -> (ListPartition)
p));
+ assertEquals(2, partitions.size());
+ assertPartition(Partitions.list("p1", p1Values, Collections.emptyMap()),
partitions.get("p1"));
+ assertPartition(Partitions.list("p2", p2Values, Collections.emptyMap()),
partitions.get("p2"));
+ }
+
+ @Test
+ void testRangePartitionRoundTrip() {
+ // Verify RANGE partition round-trips correctly on Doris 4.0.x.
+ // Behavior is identical to 3.0.x; tested separately to ensure full
coverage.
+ TableCatalog tc = catalog.asTableCatalog();
+ NameIdentifier tid =
+ NameIdentifier.of(schemaName,
GravitinoITUtils.genRandomName("t_range_partition"));
+
+ Column dateCol = Column.of("dt", Types.DateType.get(), "date", false,
false, null);
+ Distribution dist = Distributions.hash(1, NamedReference.field("dt"));
+
+ Literal todayLiteral = Literals.of("2024-07-24", Types.DateType.get());
+ Literal tomorrowLiteral = Literals.of("2024-07-25", Types.DateType.get());
+ RangePartition p1 = Partitions.range("p1", todayLiteral, Literals.NULL,
Collections.emptyMap());
+ RangePartition p2 =
+ Partitions.range("p2", tomorrowLiteral, todayLiteral,
Collections.emptyMap());
+ RangePartition p3 =
+ Partitions.range("p3", Literals.NULL, tomorrowLiteral,
Collections.emptyMap());
+ Transform[] partitioning = {
+ Transforms.range(new String[] {"dt"}, new RangePartition[] {p1, p2, p3})
+ };
+
+ tc.createTable(
+ tid,
+ new Column[] {dateCol},
+ tableComment,
+ Collections.emptyMap(),
+ partitioning,
+ dist,
+ null,
+ null);
+
+ Table loaded = tc.loadTable(tid);
+ assertEquals(1, loaded.partitioning().length);
+ assertEquals("range", loaded.partitioning()[0].name());
+
+ SupportsPartitions partitionOps = loaded.supportPartitions();
+ Map<String, RangePartition> partitions =
+ Arrays.stream(partitionOps.listPartitions())
+ .collect(Collectors.toMap(Partition::name, p -> (RangePartition)
p));
+ assertEquals(3, partitions.size());
+ assertPartition(
+ Partitions.range(
+ "p1",
+ todayLiteral,
+ Literals.of("0000-01-01", Types.DateType.get()),
+ Collections.emptyMap()),
+ partitions.get("p1"));
+ assertPartition(p2, partitions.get("p2"));
+ assertPartition(
+ Partitions.range(
+ "p3",
+ Literals.of("MAXVALUE", Types.DateType.get()),
+ tomorrowLiteral,
+ Collections.emptyMap()),
+ partitions.get("p3"));
+ }
+
private Column findColumn(Table table, String columnName) {
return Arrays.stream(table.columns())
.filter(c -> c.name().equals(columnName))
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 24a044c21f..e474c10fa7 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
@@ -1150,4 +1150,93 @@ public class CatalogDorisIT extends BaseIT {
colDefaultValues[1].defaultValue());
Assertions.assertEquals(DEFAULT_VALUE_OF_CURRENT_TIMESTAMP,
colDefaultValues[2].defaultValue());
}
+
+ @Test
+ void testListPartitionRoundTrip() {
+ // Verify LIST partition with assignments round-trips correctly on Doris
1.2.x.
+ String tableName = GravitinoITUtils.genRandomName("test_list_partition");
+ NameIdentifier tableIdentifier = NameIdentifier.of(schemaName, tableName);
+ Column col = Column.of("city", Types.VarCharType.of(50), "city", false,
false, null);
+ Distribution distribution = Distributions.hash(1,
NamedReference.field("city"));
+ Index[] indexes = Indexes.EMPTY_INDEXES;
+
+ Transform[] partitioning = {Transforms.list(new String[][] {{"city"}})};
+ TableCatalog tableCatalog = catalog.asTableCatalog();
+ tableCatalog.createTable(
+ tableIdentifier,
+ new Column[] {col},
+ table_comment,
+ Collections.emptyMap(),
+ partitioning,
+ distribution,
+ null,
+ indexes);
+
+ SupportsPartitions partitionOps =
tableCatalog.loadTable(tableIdentifier).supportPartitions();
+
+ // Add partitions
+ Literal[][] p1Values = {{Literals.of("beijing",
Types.VarCharType.of(50))}};
+ Literal[][] p2Values = {{Literals.of("shanghai",
Types.VarCharType.of(50))}};
+ partitionOps.addPartition(Partitions.list("p1", p1Values,
Collections.emptyMap()));
+ partitionOps.addPartition(Partitions.list("p2", p2Values,
Collections.emptyMap()));
+
+ // Verify round-trip: reload and check partition metadata
+ Table loadedTable = tableCatalog.loadTable(tableIdentifier);
+ SupportsPartitions loadedPartitionOps = loadedTable.supportPartitions();
+ Map<String, ListPartition> partitions =
+ Arrays.stream(loadedPartitionOps.listPartitions())
+ .collect(Collectors.toMap(Partition::name, p -> (ListPartition)
p));
+ assertEquals(2, partitions.size());
+ assertPartition(Partitions.list("p1", p1Values, Collections.emptyMap()),
partitions.get("p1"));
+ assertPartition(Partitions.list("p2", p2Values, Collections.emptyMap()),
partitions.get("p2"));
+ }
+
+ @Test
+ void testMultiColumnListPartitionRoundTrip() {
+ // Verify multi-column LIST partition round-trip:
+ // create with assignments -> loadTable -> verify partition columns and
values
+ String tableName = GravitinoITUtils.genRandomName("test_multi_col_list");
+ NameIdentifier tableIdentifier = NameIdentifier.of(schemaName, tableName);
+ Column col1 = Column.of("city", Types.VarCharType.of(50), "city", false,
false, null);
+ Column col2 = Column.of("year_col", Types.IntegerType.get(), "year",
false, false, null);
+ Distribution distribution = Distributions.hash(1,
NamedReference.field("city"));
+ Index[] indexes = Indexes.EMPTY_INDEXES;
+
+ Transform[] partitioning = {Transforms.list(new String[][] {{"city"},
{"year_col"}})};
+ TableCatalog tableCatalog = catalog.asTableCatalog();
+ tableCatalog.createTable(
+ tableIdentifier,
+ new Column[] {col1, col2},
+ table_comment,
+ Collections.emptyMap(),
+ partitioning,
+ distribution,
+ null,
+ indexes);
+
+ SupportsPartitions partitionOps =
tableCatalog.loadTable(tableIdentifier).supportPartitions();
+
+ // Add multi-column partition assignments
+ Literal[][] p1Values = {
+ {Literals.of("beijing", Types.VarCharType.of(50)),
Literals.integerLiteral(2024)}
+ };
+ Literal[][] p2Values = {
+ {Literals.of("shanghai", Types.VarCharType.of(50)),
Literals.integerLiteral(2024)}
+ };
+ partitionOps.addPartition(Partitions.list("p1", p1Values,
Collections.emptyMap()));
+ partitionOps.addPartition(Partitions.list("p2", p2Values,
Collections.emptyMap()));
+
+ // Verify round-trip
+ Table loadedTable = tableCatalog.loadTable(tableIdentifier);
+ assertEquals(1, loadedTable.partitioning().length);
+ assertEquals("list", loadedTable.partitioning()[0].name());
+
+ SupportsPartitions loadedPartitionOps = loadedTable.supportPartitions();
+ Map<String, ListPartition> partitions =
+ Arrays.stream(loadedPartitionOps.listPartitions())
+ .collect(Collectors.toMap(Partition::name, p -> (ListPartition)
p));
+ assertEquals(2, partitions.size());
+ assertPartition(Partitions.list("p1", p1Values, Collections.emptyMap()),
partitions.get("p1"));
+ assertPartition(Partitions.list("p2", p2Values, Collections.emptyMap()),
partitions.get("p2"));
+ }
}
diff --git
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/utils/TestDorisUtils.java
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/utils/TestDorisUtils.java
index 019231f39d..c26f025beb 100644
---
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/utils/TestDorisUtils.java
+++
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/utils/TestDorisUtils.java
@@ -117,6 +117,27 @@ public class TestDorisUtils {
assertTrue(transform.isPresent());
assertEquals(Transforms.list(new String[][] {{"col1"}, {"col2"}}),
transform.get());
+ // test range partition with space (Doris 3.0+ SHOW CREATE TABLE format)
+ createTableSql =
+ "CREATE TABLE `testTable` (\n`col1` date NOT NULL\n) ENGINE=OLAP\n
PARTITION BY RANGE (`col1`)\n()\n DISTRIBUTED BY HASH(`col1`) BUCKETS 2";
+ transform = DorisUtils.extractPartitionInfoFromSql(createTableSql);
+ assertTrue(transform.isPresent());
+ assertEquals(Transforms.range(new String[] {"col1"}), transform.get());
+
+ // test list partition with space (Doris 3.0+ SHOW CREATE TABLE format)
+ createTableSql =
+ "CREATE TABLE `testTable` (\n`col1` int(11) NOT NULL\n) ENGINE=OLAP\n
PARTITION BY LIST (`col1`)\n()\n DISTRIBUTED BY HASH(`col1`) BUCKETS 2";
+ transform = DorisUtils.extractPartitionInfoFromSql(createTableSql);
+ assertTrue(transform.isPresent());
+ assertEquals(Transforms.list(new String[][] {{"col1"}}), transform.get());
+
+ // test multi-column list partition with space
+ createTableSql =
+ "CREATE TABLE `testTable` (\n`col1` date NOT NULL,\n`col2` int(11) NOT
NULL\n) ENGINE=OLAP\n PARTITION BY LIST (`col1`, `col2`)\n()\n DISTRIBUTED BY
HASH(`col1`) BUCKETS 2";
+ transform = DorisUtils.extractPartitionInfoFromSql(createTableSql);
+ assertTrue(transform.isPresent());
+ assertEquals(Transforms.list(new String[][] {{"col1"}, {"col2"}}),
transform.get());
+
// test non-partitioned table
createTableSql =
"CREATE TABLE `testTable` (\n`testColumn` STRING NOT NULL COMMENT
'test comment'\n) ENGINE=OLAP\nCOMMENT \"test comment\"";