This is an automated email from the ASF dual-hosted git repository. github-actions[bot] pushed a commit to branch cherry-pick-6968f0b0-to-branch-1.3 in repository https://gitbox.apache.org/repos/asf/gravitino.git
commit 42cec0b778ff012c38d63d42f68aba4a3a9af38c Author: Qi Yu <[email protected]> AuthorDate: Mon Oct 19 15:46:44 2026 +0800 [#13916] fix(jdbc): reject unsupported StarRocks and OceanBase purge (#13917) ### What changes were proposed in this pull request? Reject unsupported table purge in the StarRocks and OceanBase JDBC catalogs instead of executing `TRUNCATE TABLE`. Remove StarRocks' two-argument purge SQL override so the actual JDBC purge path reaches its existing unsupported-operation check. Make OceanBase report the same unsupported-operation contract. Add regression tests through `purge()` that verify the exception, no destructive SQL execution, and connection release; also verify ordinary `drop()` still executes `DROP TABLE`. Update the existing OceanBase integration test to expect unsupported purge for both present and absent tables and verify rejection preserves the existing table. Document in both catalog pages that drop runs `DROP TABLE` and purge is rejected without changing the table. ### Why are the changes needed? Both catalogs currently clear the data while retaining the table, then report `dropped: true`. This violates the table-purge contract and can cause Gravitino to remove its registration for a table that still exists. Fix: #13916 ### Does this PR introduce _any_ user-facing change? Yes. Purge on these two catalogs now reports an unsupported-operation error instead of clearing table data and reporting successful deletion. Use ordinary drop to delete a table. This does not claim that ordinary drop skips the backend's recycle bin. ### How was this patch tested? - All non-Docker unit tests in both affected modules: 22 passed (StarRocks 13, OceanBase 9). - Spotless checks and `git diff --check` passed. - Restored both old implementations temporarily: both new purge regressions failed because no unsupported-operation exception was thrown. The fixes were restored afterward. - Focused OceanBase Docker integration test `CatalogOceanBaseIT.testNameSpec`: 1 passed against a real OceanBase container and embedded Gravitino server. --- .../operation/OceanBaseTableOperations.java | 3 +- .../integration/test/CatalogOceanBaseIT.java | 6 +++- .../TestOceanBaseTableOperationsSqlGeneration.java | 34 ++++++++++++++++++++++ .../operations/StarRocksTableOperations.java | 6 ---- .../TestStarRocksTableOperationsSqlGeneration.java | 34 ++++++++++++++++++++++ docs/jdbc-oceanbase-catalog.md | 7 +++++ docs/jdbc-starrocks-catalog.md | 7 +++++ 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/catalogs-contrib/catalog-jdbc-oceanbase/src/main/java/org/apache/gravitino/catalog/oceanbase/operation/OceanBaseTableOperations.java b/catalogs-contrib/catalog-jdbc-oceanbase/src/main/java/org/apache/gravitino/catalog/oceanbase/operation/OceanBaseTableOperations.java index aa9a49cf53..87399f8165 100644 --- a/catalogs-contrib/catalog-jdbc-oceanbase/src/main/java/org/apache/gravitino/catalog/oceanbase/operation/OceanBaseTableOperations.java +++ b/catalogs-contrib/catalog-jdbc-oceanbase/src/main/java/org/apache/gravitino/catalog/oceanbase/operation/OceanBaseTableOperations.java @@ -196,7 +196,8 @@ public class OceanBaseTableOperations extends JdbcTableOperations { @Override protected String generatePurgeTableSql(String tableName) { - return String.format("TRUNCATE TABLE `%s`", tableName); + throw new UnsupportedOperationException( + "OceanBase does not support purge table in Gravitino, please use drop table"); } /** diff --git a/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/integration/test/CatalogOceanBaseIT.java b/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/integration/test/CatalogOceanBaseIT.java index 260d851ac7..63532f42c3 100644 --- a/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/integration/test/CatalogOceanBaseIT.java +++ b/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/integration/test/CatalogOceanBaseIT.java @@ -1460,9 +1460,13 @@ public class CatalogOceanBaseIT extends BaseIT { catalog.asTableCatalog().listTables(Namespace.of(testSchemaName)); Assertions.assertTrue(Arrays.stream(tableIdents).anyMatch(t -> t.name().equals(testTableName))); + Assertions.assertThrows( + UnsupportedOperationException.class, () -> catalog.asTableCatalog().purgeTable(tableIdent)); + Assertions.assertTrue(catalog.asTableCatalog().tableExists(tableIdent)); Assertions.assertTrue(catalog.asTableCatalog().dropTable(tableIdent)); Assertions.assertFalse(catalog.asTableCatalog().tableExists(tableIdent)); - Assertions.assertFalse(catalog.asTableCatalog().purgeTable(tableIdent)); + Assertions.assertThrows( + UnsupportedOperationException.class, () -> catalog.asTableCatalog().purgeTable(tableIdent)); catalog.asSchemas().dropSchema(testSchemaName, true); // sql injection diff --git a/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/operation/TestOceanBaseTableOperationsSqlGeneration.java b/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/operation/TestOceanBaseTableOperationsSqlGeneration.java index 2897660bfc..74ea40b2d5 100644 --- a/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/operation/TestOceanBaseTableOperationsSqlGeneration.java +++ b/catalogs-contrib/catalog-jdbc-oceanbase/src/test/java/org/apache/gravitino/catalog/oceanbase/operation/TestOceanBaseTableOperationsSqlGeneration.java @@ -19,9 +19,11 @@ package org.apache.gravitino.catalog.oceanbase.operation; import java.util.Collections; +import java.util.List; import org.apache.gravitino.catalog.jdbc.JdbcColumn; import org.apache.gravitino.catalog.jdbc.converter.JdbcColumnDefaultValueConverter; import org.apache.gravitino.catalog.jdbc.converter.JdbcExceptionConverter; +import org.apache.gravitino.catalog.jdbc.utils.ConnectionCountingDataSource; import org.apache.gravitino.catalog.oceanbase.converter.OceanBaseTypeConverter; import org.apache.gravitino.rel.expressions.distributions.Distributions; import org.apache.gravitino.rel.expressions.literals.Literals; @@ -40,6 +42,11 @@ public class TestOceanBaseTableOperationsSqlGeneration { super.columnDefaultValueConverter = new JdbcColumnDefaultValueConverter(); } + private TestableOceanBaseTableOperations(ConnectionCountingDataSource connections) { + this(); + dataSource = connections.dataSource(); + } + public String createTableSql(String tableName, JdbcColumn[] columns) { return generateCreateTableSql( tableName, @@ -52,6 +59,33 @@ public class TestOceanBaseTableOperationsSqlGeneration { } } + @Test + void testPurgeIsRejectedWithoutExecutingSql() { + ConnectionCountingDataSource connections = new ConnectionCountingDataSource(); + TestableOceanBaseTableOperations ops = new TestableOceanBaseTableOperations(connections); + + UnsupportedOperationException exception = + Assertions.assertThrows( + UnsupportedOperationException.class, () -> ops.purge("database", "test_table")); + + Assertions.assertEquals( + "OceanBase does not support purge table in Gravitino, please use drop table", + exception.getMessage()); + Assertions.assertTrue(connections.executedSql().isEmpty()); + Assertions.assertEquals(0, connections.borrowed()); + } + + @Test + void testDropStillExecutesDropTable() { + ConnectionCountingDataSource connections = new ConnectionCountingDataSource(); + TestableOceanBaseTableOperations ops = new TestableOceanBaseTableOperations(connections); + + Assertions.assertTrue(ops.drop("database", "test_table")); + + Assertions.assertEquals(List.of("DROP TABLE `test_table`"), connections.executedSql()); + Assertions.assertEquals(0, connections.borrowed()); + } + @Test public void testCreateTableWithEmptyStringDefaultValue() { TestableOceanBaseTableOperations ops = new TestableOceanBaseTableOperations(); diff --git a/catalogs/catalog-jdbc-starrocks/src/main/java/org/apache/gravitino/catalog/starrocks/operations/StarRocksTableOperations.java b/catalogs/catalog-jdbc-starrocks/src/main/java/org/apache/gravitino/catalog/starrocks/operations/StarRocksTableOperations.java index e123be6103..319ea09739 100644 --- a/catalogs/catalog-jdbc-starrocks/src/main/java/org/apache/gravitino/catalog/starrocks/operations/StarRocksTableOperations.java +++ b/catalogs/catalog-jdbc-starrocks/src/main/java/org/apache/gravitino/catalog/starrocks/operations/StarRocksTableOperations.java @@ -300,16 +300,10 @@ public class StarRocksTableOperations extends JdbcTableOperations { @Override protected String generatePurgeTableSql(String tableName) { - // never called, as implemented generatePurgeTableSql(String databaseName, String tableName) throw new UnsupportedOperationException( "StarRocks does not support purge table in Gravitino, please use drop table"); } - @Override - protected String generatePurgeTableSql(String databaseName, String tableName) { - return String.format("TRUNCATE TABLE `%s`.`%s`", databaseName, tableName); - } - @Override protected Distribution getDistributionInfo( Connection connection, String databaseName, String tableName) throws SQLException { diff --git a/catalogs/catalog-jdbc-starrocks/src/test/java/org/apache/gravitino/catalog/starrocks/operation/TestStarRocksTableOperationsSqlGeneration.java b/catalogs/catalog-jdbc-starrocks/src/test/java/org/apache/gravitino/catalog/starrocks/operation/TestStarRocksTableOperationsSqlGeneration.java index 12195a08cb..5fc1a2114a 100644 --- a/catalogs/catalog-jdbc-starrocks/src/test/java/org/apache/gravitino/catalog/starrocks/operation/TestStarRocksTableOperationsSqlGeneration.java +++ b/catalogs/catalog-jdbc-starrocks/src/test/java/org/apache/gravitino/catalog/starrocks/operation/TestStarRocksTableOperationsSqlGeneration.java @@ -19,11 +19,13 @@ package org.apache.gravitino.catalog.starrocks.operation; import java.util.Collections; +import java.util.List; import org.apache.gravitino.StringIdentifier; import org.apache.gravitino.catalog.jdbc.JdbcColumn; import org.apache.gravitino.catalog.jdbc.JdbcTable; import org.apache.gravitino.catalog.jdbc.converter.JdbcColumnDefaultValueConverter; import org.apache.gravitino.catalog.jdbc.converter.JdbcExceptionConverter; +import org.apache.gravitino.catalog.jdbc.utils.ConnectionCountingDataSource; import org.apache.gravitino.catalog.starrocks.converter.StarRocksTypeConverter; import org.apache.gravitino.catalog.starrocks.operations.StarRocksTableOperations; import org.apache.gravitino.rel.TableChange; @@ -47,6 +49,11 @@ public class TestStarRocksTableOperationsSqlGeneration { super.columnDefaultValueConverter = new JdbcColumnDefaultValueConverter(); } + private TestableStarRocksTableOperations(ConnectionCountingDataSource connections) { + this(); + dataSource = connections.dataSource(); + } + public String createTableSql( String tableName, JdbcColumn[] columns, Distribution distribution) { return createTableSql(tableName, columns, distribution, "comment"); @@ -79,6 +86,33 @@ public class TestStarRocksTableOperationsSqlGeneration { } } + @Test + void testPurgeIsRejectedWithoutExecutingSql() { + ConnectionCountingDataSource connections = new ConnectionCountingDataSource(); + TestableStarRocksTableOperations ops = new TestableStarRocksTableOperations(connections); + + UnsupportedOperationException exception = + Assertions.assertThrows( + UnsupportedOperationException.class, () -> ops.purge("database", "test_table")); + + Assertions.assertEquals( + "StarRocks does not support purge table in Gravitino, please use drop table", + exception.getMessage()); + Assertions.assertTrue(connections.executedSql().isEmpty()); + Assertions.assertEquals(0, connections.borrowed()); + } + + @Test + void testDropStillExecutesDropTable() { + ConnectionCountingDataSource connections = new ConnectionCountingDataSource(); + TestableStarRocksTableOperations ops = new TestableStarRocksTableOperations(connections); + + Assertions.assertTrue(ops.drop("database", "test_table")); + + Assertions.assertEquals(List.of("DROP TABLE `test_table`"), connections.executedSql()); + Assertions.assertEquals(0, connections.borrowed()); + } + @Test public void testCreateTableWithEmptyStringDefaultValue() { TestableStarRocksTableOperations ops = new TestableStarRocksTableOperations(); diff --git a/docs/jdbc-oceanbase-catalog.md b/docs/jdbc-oceanbase-catalog.md index 22ffc1c0ec..9e0b99e7a5 100644 --- a/docs/jdbc-oceanbase-catalog.md +++ b/docs/jdbc-oceanbase-catalog.md @@ -260,6 +260,13 @@ The OceanBase catalog does not support creating partitioned tables in the curren Refer to [Manage Relational Metadata Using Gravitino](./manage-relational-metadata-using-gravitino.md#table-operations) for more details. +#### Drop and Purge Table + +- Dropping a table runs `DROP TABLE` in OceanBase. Whether OceanBase keeps the dropped table in its + recycle bin depends on the OceanBase configuration. +- Purging a table is not supported. A purge request fails with an unsupported-operation error, and + the table and its data stay unchanged. Use drop instead. + #### Alter Table Operations Gravitino supports these table alteration operations: diff --git a/docs/jdbc-starrocks-catalog.md b/docs/jdbc-starrocks-catalog.md index 178f8bf4d1..76abc206a3 100644 --- a/docs/jdbc-starrocks-catalog.md +++ b/docs/jdbc-starrocks-catalog.md @@ -177,6 +177,13 @@ For the `RANDOM` distribution strategy, Gravitino uses the `EVEN` to represent i Refer to [Manage Relational Metadata Using Gravitino](./manage-relational-metadata-using-gravitino.md#table-operations) for more details. +#### Drop and Purge Table + +- Dropping a table runs `DROP TABLE` in StarRocks. Whether StarRocks keeps the dropped table in its + recycle bin depends on the StarRocks configuration. +- Purging a table is not supported. A purge request fails with an unsupported-operation error, and + the table and its data stay unchanged. Use drop instead. + #### Alter Table Operations Gravitino supports these table alteration operations:
