This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push: new f2556ba1823 [feature](insert)support external hive truncate table DDL (#37659) f2556ba1823 is described below commit f2556ba1823fa2a1f79253151703a42cdb272d39 Author: slothever <18522955+w...@users.noreply.github.com> AuthorDate: Fri Jul 12 22:37:47 2024 +0800 [feature](insert)support external hive truncate table DDL (#37659) pick: #36801 --- .../apache/doris/analysis/TruncateTableStmt.java | 3 - .../main/java/org/apache/doris/catalog/Env.java | 6 +- .../org/apache/doris/datasource/CatalogIf.java | 3 + .../apache/doris/datasource/ExternalCatalog.java | 23 +++++ .../doris/datasource/hive/HMSCachedClient.java | 2 + .../doris/datasource/hive/HiveMetadataOps.java | 16 ++++ .../hive/PostgreSQLJdbcHMSCachedClient.java | 4 + .../datasource/hive/ThriftHMSCachedClient.java | 19 +++- .../datasource/iceberg/IcebergMetadataOps.java | 5 ++ .../datasource/operations/ExternalMetadataOps.java | 8 ++ .../doris/datasource/TestHMSCachedClient.java | 3 + .../hive/ddl/test_hive_truncate_table.out | 24 +++++ .../hive/ddl/test_hive_truncate_table.groovy | 100 +++++++++++++++++++++ 13 files changed, 210 insertions(+), 6 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TruncateTableStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TruncateTableStmt.java index a275879692c..1a9fbd3bafd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TruncateTableStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TruncateTableStmt.java @@ -23,7 +23,6 @@ import org.apache.doris.common.ErrorCode; import org.apache.doris.common.ErrorReport; import org.apache.doris.common.UserException; import org.apache.doris.common.util.InternalDatabaseUtil; -import org.apache.doris.common.util.Util; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; @@ -44,8 +43,6 @@ public class TruncateTableStmt extends DdlStmt { public void analyze(Analyzer analyzer) throws AnalysisException, UserException { super.analyze(analyzer); tblRef.getName().analyze(analyzer); - // disallow external catalog - Util.prohibitExternalCatalog(tblRef.getName().getCtl(), this.getClass().getSimpleName()); if (tblRef.hasExplicitAlias()) { throw new AnalysisException("Not support truncate table with alias"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java index ea8ffd91d2e..9b73a4517f0 100755 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java @@ -5427,8 +5427,10 @@ public class Env { * otherwise, it will only truncate those specified partitions. * */ - public void truncateTable(TruncateTableStmt truncateTableStmt) throws DdlException { - getInternalCatalog().truncateTable(truncateTableStmt); + public void truncateTable(TruncateTableStmt stmt) throws DdlException { + CatalogIf<?> catalogIf = catalogMgr.getCatalogOrException(stmt.getTblRef().getName().getCtl(), + catalog -> new DdlException(("Unknown catalog " + catalog))); + catalogIf.truncateTable(stmt); } public void replayTruncateTable(TruncateTableInfo info) throws MetaNotFoundException { diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java index ceee1a68157..a79897c67df 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java @@ -22,6 +22,7 @@ import org.apache.doris.analysis.CreateTableStmt; import org.apache.doris.analysis.DropDbStmt; import org.apache.doris.analysis.DropTableStmt; import org.apache.doris.analysis.TableName; +import org.apache.doris.analysis.TruncateTableStmt; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.TableIf; @@ -194,4 +195,6 @@ public interface CatalogIf<T extends DatabaseIf> { boolean createTable(CreateTableStmt stmt) throws UserException; void dropTable(DropTableStmt stmt) throws DdlException; + + void truncateTable(TruncateTableStmt truncateTableStmt) throws DdlException; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java index 0fbedf57e66..82f4d309c82 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java @@ -22,6 +22,8 @@ import org.apache.doris.analysis.CreateTableStmt; import org.apache.doris.analysis.DropDbStmt; import org.apache.doris.analysis.DropTableStmt; import org.apache.doris.analysis.TableName; +import org.apache.doris.analysis.TableRef; +import org.apache.doris.analysis.TruncateTableStmt; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.InfoSchemaDb; @@ -821,4 +823,25 @@ public abstract class ExternalCatalog } return ret; } + + @Override + public void truncateTable(TruncateTableStmt stmt) throws DdlException { + makeSureInitialized(); + if (metadataOps == null) { + throw new UnsupportedOperationException("Truncate table not supported in " + getName()); + } + try { + TableRef tableRef = stmt.getTblRef(); + TableName tableName = tableRef.getName(); + // delete all table data if null + List<String> partitions = null; + if (tableRef.getPartitionNames() != null) { + partitions = tableRef.getPartitionNames().getPartitionNames(); + } + metadataOps.truncateTable(tableName.getDb(), tableName.getTbl(), partitions); + } catch (Exception e) { + LOG.warn("Failed to drop a table", e); + throw e; + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSCachedClient.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSCachedClient.java index c9d0ce1736b..1ac77972053 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSCachedClient.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSCachedClient.java @@ -94,6 +94,8 @@ public interface HMSCachedClient { void dropTable(String dbName, String tableName); + void truncateTable(String dbName, String tblName, List<String> partitions); + void createTable(TableMetadata catalogTable, boolean ignoreIfExists); void updateTableStatistics( diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetadataOps.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetadataOps.java index 70c61875b8a..7267297c93e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetadataOps.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetadataOps.java @@ -251,6 +251,22 @@ public class HiveMetadataOps implements ExternalMetadataOps { } } + @Override + public void truncateTable(String dbName, String tblName, List<String> partitions) throws DdlException { + ExternalDatabase<?> db = catalog.getDbNullable(dbName); + if (db == null) { + throw new DdlException("Failed to get database: '" + dbName + "' in catalog: " + catalog.getName()); + } + try { + client.truncateTable(dbName, tblName, partitions); + } catch (Exception e) { + throw new DdlException(e.getMessage(), e); + } + Env.getCurrentEnv().getExtMetaCacheMgr().invalidateTableCache(catalog.getId(), dbName, tblName); + db.setLastUpdateTime(System.currentTimeMillis()); + db.setUnInitialized(true); + } + @Override public List<String> listTableNames(String dbName) { return client.getAllTables(dbName); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/PostgreSQLJdbcHMSCachedClient.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/PostgreSQLJdbcHMSCachedClient.java index 8e41b48bfdd..0cdb3e469c2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/PostgreSQLJdbcHMSCachedClient.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/PostgreSQLJdbcHMSCachedClient.java @@ -546,6 +546,10 @@ public class PostgreSQLJdbcHMSCachedClient extends JdbcHMSCachedClient { throw new NotImplementedException("PostgreSQL dropDatabase not implemented"); } + public void truncateTable(String dbName, String tblName, List<String> partitions) { + throw new NotImplementedException("PostgreSQL truncateTable not implemented"); + } + public void createTable(TableMetadata hiveTable, boolean ignoreIfExists) { throw new NotImplementedException("PostgreSQL createTable not implemented"); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/ThriftHMSCachedClient.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/ThriftHMSCachedClient.java index 17fbcb09b02..55d8ffc2e02 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/ThriftHMSCachedClient.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/ThriftHMSCachedClient.java @@ -244,6 +244,23 @@ public class ThriftHMSCachedClient implements HMSCachedClient { } } + @Override + public void truncateTable(String dbName, String tblName, List<String> partitions) { + try (ThriftHMSClient client = getClient()) { + try { + ugiDoAs(() -> { + client.client.truncateTable(dbName, tblName, partitions); + return null; + }); + } catch (Exception e) { + client.setThrowable(e); + throw e; + } + } catch (Exception e) { + throw new HMSClientException("failed to truncate table %s in db %s.", e, tblName, dbName); + } + } + @Override public boolean tableExists(String dbName, String tblName) { try (ThriftHMSClient client = getClient()) { @@ -272,7 +289,7 @@ public class ThriftHMSCachedClient implements HMSCachedClient { throw e; } } catch (Exception e) { - throw new HMSClientException("failed to check if table %s in db %s exists", e, tblName, dbName); + throw new HMSClientException("failed to list partitions in table '%s.%s'.", e, dbName, tblName); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java index 7161f48680a..c7fef68ee97 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java @@ -173,4 +173,9 @@ public class IcebergMetadataOps implements ExternalMetadataOps { catalog.dropTable(TableIdentifier.of(dbName, tableName)); db.setUnInitialized(true); } + + @Override + public void truncateTable(String dbName, String tblName, List<String> partitions) { + throw new UnsupportedOperationException("Truncate Iceberg table is not supported."); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/operations/ExternalMetadataOps.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/operations/ExternalMetadataOps.java index 9426442cebb..0333124b352 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/operations/ExternalMetadataOps.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/operations/ExternalMetadataOps.java @@ -60,6 +60,14 @@ public interface ExternalMetadataOps { */ void dropTable(DropTableStmt stmt) throws DdlException; + /** + * + * @param dbName + * @param tblName + * @param partitions + */ + void truncateTable(String dbName, String tblName, List<String> partitions) throws DdlException; + /** * * @return diff --git a/fe/fe-core/src/test/java/org/apache/doris/datasource/TestHMSCachedClient.java b/fe/fe-core/src/test/java/org/apache/doris/datasource/TestHMSCachedClient.java index 6f969257245..f3cb918d6f5 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/datasource/TestHMSCachedClient.java +++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/TestHMSCachedClient.java @@ -235,6 +235,9 @@ public class TestHMSCachedClient implements HMSCachedClient { this.partitions.remove(new HMSTransaction.DatabaseTableName(dbName, tableName)); } + @Override + public void truncateTable(String dbName, String tblName, List<String> partitions) {} + @Override public void createTable(TableMetadata tbl, boolean ignoreIfExists) { String dbName = tbl.getDbName(); diff --git a/regression-test/data/external_table_p0/hive/ddl/test_hive_truncate_table.out b/regression-test/data/external_table_p0/hive/ddl/test_hive_truncate_table.out new file mode 100644 index 00000000000..24d6cade5d2 --- /dev/null +++ b/regression-test/data/external_table_p0/hive/ddl/test_hive_truncate_table.out @@ -0,0 +1,24 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !truncate_01_pre -- +222 aoe +3234424 44 + +-- !truncate_01 -- + +-- !truncate_02 -- + +-- !truncate_03 -- + +-- !truncate_04_pre -- +33 awe wuu 2023-02-04 +5535 3 dre 2023-04-04 + +-- !truncate_04 -- + +-- !truncate_06 -- +44 etg wuweu 2022-02-04 +555 etgf wet 2021-05-06 +88 etg wuweu 2022-01-04 +95 etgf hiyr 2021-05-06 + +-- !truncate_09 -- diff --git a/regression-test/suites/external_table_p0/hive/ddl/test_hive_truncate_table.groovy b/regression-test/suites/external_table_p0/hive/ddl/test_hive_truncate_table.groovy new file mode 100644 index 00000000000..94082d0287f --- /dev/null +++ b/regression-test/suites/external_table_p0/hive/ddl/test_hive_truncate_table.groovy @@ -0,0 +1,100 @@ +// 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_hive_truncate_table", "p0,external,hive,external_docker,external_docker_hive") { + String enabled = context.config.otherConfigs.get("enableHiveTest") + if (enabled != null && enabled.equalsIgnoreCase("true")) { + String externalEnvIp = context.config.otherConfigs.get("externalEnvIp") + String hms_port = context.config.otherConfigs.get("hive3HmsPort") + String hdfs_port = context.config.otherConfigs.get("hive3HdfsPort") + String catalog_name = "test_hive3_truncate_table" + sql """drop catalog if exists ${catalog_name};""" + + sql """ + create catalog if not exists ${catalog_name} properties ( + 'type'='hms', + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'use_meta_cache' = 'true', + 'hive.version'='3.0' + ); + """ + + logger.info("catalog " + catalog_name + " created") + sql """switch ${catalog_name};""" + logger.info("switched to catalog " + catalog_name) + sql """create database if not exists `hive_truncate`;""" + sql """use `hive_truncate`;""" + + // 1. test no partition table + sql """create table if not exists `table_no_pars`(col1 bigint, col2 string) engine=hive; """ + sql """truncate table table_no_pars;""" + + sql """insert into `table_no_pars` values(3234424, '44'); """ + sql """insert into `table_no_pars` values(222, 'aoe'); """ + order_qt_truncate_01_pre """ select * from table_no_pars; """ + sql """truncate table table_no_pars;""" + order_qt_truncate_01 """ select * from table_no_pars; """ + + sql """insert into `table_no_pars` values(3234424, '44'); """ + sql """truncate table hive_truncate.table_no_pars;""" + order_qt_truncate_02 """ select * from table_no_pars; """ + + sql """insert into `table_no_pars` values(222, 'aoe'); """ + sql """truncate table ${catalog_name}.hive_truncate.table_no_pars;""" + order_qt_truncate_03 """ select * from table_no_pars; """ + sql """insert into `table_no_pars` values(222, 'aoe'); """ + sql """drop table table_no_pars """ + + // 2. test partition table + sql """create table if not exists `table_with_pars`(col1 bigint, col2 string, pt1 varchar, pt2 date) engine=hive + partition by list(pt1, pt2)() """ + sql """truncate table table_with_pars;""" + + sql """insert into `table_with_pars` values(33, 'awe', 'wuu', '2023-02-04') """ + sql """insert into `table_with_pars` values(5535, '3', 'dre', '2023-04-04') """ + order_qt_truncate_04_pre """ select * from table_with_pars; """ + sql """truncate table table_with_pars;""" + order_qt_truncate_04 """ select * from table_with_pars; """ + + // 3. test partition table and truncate partitions + sql """insert into `table_with_pars` values(44, 'etg', 'wuweu', '2022-02-04') """ + sql """insert into `table_with_pars` values(88, 'etg', 'wuweu', '2022-01-04') """ + sql """insert into `table_with_pars` values(095, 'etgf', 'hiyr', '2021-05-06') """ + sql """insert into `table_with_pars` values(555, 'etgf', 'wet', '2021-05-06') """ + // sql """truncate table hive_truncate.table_with_pars partition pt1;""" + // order_qt_truncate_05 """ select * from table_with_pars; """ + // sql """truncate table hive_truncate.table_with_pars partition pt2;""" + order_qt_truncate_06 """ select * from table_with_pars; """ + + sql """insert into `table_with_pars` values(22, 'ttt', 'gggw', '2022-02-04')""" + sql """insert into `table_with_pars` values(44, 'etg', 'wuweu', '2022-02-04') """ + sql """insert into `table_with_pars` values(88, 'etg', 'wuweu', '2022-01-04') """ + sql """insert into `table_with_pars` values(095, 'etgf', 'hiyr', '2021-05-06') """ + sql """insert into `table_with_pars` values(555, 'etgf', 'wet', '2021-05-06') """ + // sql """truncate table ${catalog_name}.hive_truncate.table_with_pars partition pt1;""" + // order_qt_truncate_07 """ select * from table_with_pars; """ + // sql """truncate table ${catalog_name}.hive_truncate.table_with_pars partition pt2;""" + // order_qt_truncate_08 """ select * from table_with_pars; """ + sql """truncate table table_with_pars""" + order_qt_truncate_09 """ select * from table_with_pars; """ + + sql """drop table table_with_pars """ + sql """drop database hive_truncate;""" + sql """drop catalog ${catalog_name};""" + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org