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

jinsongzhou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/amoro.git


The following commit(s) were added to refs/heads/master by this push:
     new ba025277a [AMORO-2629]Mixed hive refractor (#2691)
ba025277a is described below

commit ba025277ae8554243f2809ca0ff890168e6e1d32
Author: Wang Tao <[email protected]>
AuthorDate: Fri Apr 12 12:03:58 2024 +0800

    [AMORO-2629]Mixed hive refractor (#2691)
    
    * issue_2629 mixed-hive refractor
    
    * issue_2629 mixed-hive refractor
    
    * issue_2629 mixed-hive refractor
    
    * issue_2629 mixed-hive refractor
    
    * issue_2629 mixed-hive refractor
---
 .../arctic/server/catalog/CatalogBuilder.java      |   4 -
 .../server/catalog/MixedHiveCatalogImpl.java       |   5 +-
 .../dashboard/controller/TableController.java      |  17 +-
 .../arctic/server/table/AMSTableTestBase.java      |  40 +-
 .../server/table/TestTableRuntimeHandler.java      |   7 +-
 .../arctic/server/table/TestTableService.java      |  29 +-
 .../netease/arctic/catalog/BasicArcticCatalog.java |  20 +-
 .../com/netease/arctic/catalog/MixedTables.java    |   4 +
 .../java/com/netease/arctic/hive/HMSClient.java    |   2 +
 .../com/netease/arctic/hive/HMSClientImpl.java     |   6 +
 .../arctic/hive/catalog/ArcticHiveCatalog.java     | 461 +++++++++++++++++++--
 .../arctic/hive/catalog/MixedHiveTables.java       | 142 ++++++-
 .../arctic/hive/catalog/HiveCatalogTestHelper.java |   5 +-
 .../arctic/spark/ArcticSparkExtensions.scala       |   7 +
 .../arctic/spark/ArcticSparkExtensions.scala       |   7 +
 15 files changed, 681 insertions(+), 75 deletions(-)

diff --git 
a/ams/server/src/main/java/com/netease/arctic/server/catalog/CatalogBuilder.java
 
b/ams/server/src/main/java/com/netease/arctic/server/catalog/CatalogBuilder.java
index 0eb6abd94..3f276a30b 100644
--- 
a/ams/server/src/main/java/com/netease/arctic/server/catalog/CatalogBuilder.java
+++ 
b/ams/server/src/main/java/com/netease/arctic/server/catalog/CatalogBuilder.java
@@ -82,10 +82,6 @@ public class CatalogBuilder {
       case CATALOG_TYPE_CUSTOM:
         return new ExternalCatalog(catalogMeta);
       case CATALOG_TYPE_HIVE:
-        if (tableFormats.size() == 1 && 
tableFormat.equals(TableFormat.MIXED_HIVE)) {
-          return new MixedHiveCatalogImpl(catalogMeta);
-        }
-        // if tableFormats.size() > 1 , we need fulfill the ams uri in 
catalogProperty
         String amsUri = getAmsURI(serverConfiguration);
         catalogMeta.getCatalogProperties().put(CatalogMetaProperties.AMS_URI, 
amsUri);
         return new ExternalCatalog(catalogMeta);
diff --git 
a/ams/server/src/main/java/com/netease/arctic/server/catalog/MixedHiveCatalogImpl.java
 
b/ams/server/src/main/java/com/netease/arctic/server/catalog/MixedHiveCatalogImpl.java
index cda5f9190..dd004413d 100644
--- 
a/ams/server/src/main/java/com/netease/arctic/server/catalog/MixedHiveCatalogImpl.java
+++ 
b/ams/server/src/main/java/com/netease/arctic/server/catalog/MixedHiveCatalogImpl.java
@@ -21,7 +21,6 @@ package com.netease.arctic.server.catalog;
 import com.netease.arctic.AmoroTable;
 import com.netease.arctic.TableFormat;
 import com.netease.arctic.api.CatalogMeta;
-import com.netease.arctic.catalog.MixedTables;
 import com.netease.arctic.formats.mixed.MixedTable;
 import com.netease.arctic.hive.CachedHiveClientPool;
 import com.netease.arctic.hive.HMSClient;
@@ -38,7 +37,7 @@ import org.apache.thrift.TException;
 import java.util.List;
 
 public class MixedHiveCatalogImpl extends InternalCatalog {
-  protected MixedTables tables;
+  protected MixedHiveTables tables;
   private volatile CachedHiveClientPool hiveClientPool;
 
   protected MixedHiveCatalogImpl(CatalogMeta catalogMeta) {
@@ -133,7 +132,7 @@ public class MixedHiveCatalogImpl extends InternalCatalog {
     return hiveClientPool;
   }
 
-  private MixedTables tables() {
+  private MixedHiveTables tables() {
     return tables;
   }
 }
diff --git 
a/ams/server/src/main/java/com/netease/arctic/server/dashboard/controller/TableController.java
 
b/ams/server/src/main/java/com/netease/arctic/server/dashboard/controller/TableController.java
index d0ad2b3ac..78e136f89 100644
--- 
a/ams/server/src/main/java/com/netease/arctic/server/dashboard/controller/TableController.java
+++ 
b/ams/server/src/main/java/com/netease/arctic/server/dashboard/controller/TableController.java
@@ -199,13 +199,22 @@ public class TableController {
     String amsUri = AmsUtil.getAMSThriftAddress(serviceConfig, 
Constants.THRIFT_TABLE_SERVICE_NAME);
     catalogMeta.putToCatalogProperties(CatalogMetaProperties.AMS_URI, amsUri);
     TableMetaStore tableMetaStore = 
ArcticCatalogUtil.buildMetaStore(catalogMeta);
+    // check whether catalog support MIXED_HIVE format.
+    Set<TableFormat> tableFormats = 
ArcticCatalogUtil.tableFormats(catalogMeta);
+    Preconditions.checkState(
+        tableFormats.contains(TableFormat.MIXED_HIVE),
+        "Catalog %s does not support MIXED_HIVE format",
+        catalog);
+    // we should only keep MIXED_HIVE format,
+    // so `CatalogLoader.createCatalog` can get right CatalogImpl through 
calling catalogImpl.
+    Map<String, String> originCatalogProperties = 
catalogMeta.getCatalogProperties();
+    Map<String, String> catalogProperties = new 
HashMap<>(originCatalogProperties);
+    catalogProperties.put(CatalogMetaProperties.TABLE_FORMATS, 
TableFormat.MIXED_HIVE.name());
+
     ArcticHiveCatalog arcticHiveCatalog =
         (ArcticHiveCatalog)
             CatalogLoader.createCatalog(
-                catalog,
-                catalogMeta.getCatalogType(),
-                catalogMeta.getCatalogProperties(),
-                tableMetaStore);
+                catalog, catalogMeta.getCatalogType(), catalogProperties, 
tableMetaStore);
 
     tableUpgradeExecutor.execute(
         () -> {
diff --git 
a/ams/server/src/test/java/com/netease/arctic/server/table/AMSTableTestBase.java
 
b/ams/server/src/test/java/com/netease/arctic/server/table/AMSTableTestBase.java
index b36f2fe0f..1bdb63c3a 100644
--- 
a/ams/server/src/test/java/com/netease/arctic/server/table/AMSTableTestBase.java
+++ 
b/ams/server/src/test/java/com/netease/arctic/server/table/AMSTableTestBase.java
@@ -30,6 +30,8 @@ import com.netease.arctic.catalog.CatalogLoader;
 import com.netease.arctic.catalog.CatalogTestHelper;
 import com.netease.arctic.catalog.MixedTables;
 import com.netease.arctic.hive.TestHMS;
+import com.netease.arctic.hive.catalog.ArcticHiveCatalog;
+import com.netease.arctic.properties.CatalogMetaProperties;
 import com.netease.arctic.table.ArcticTable;
 import com.netease.arctic.utils.ArcticCatalogUtil;
 import com.netease.arctic.utils.ConvertStructUtil;
@@ -47,6 +49,7 @@ import org.junit.Rule;
 import org.junit.rules.TemporaryFolder;
 
 import java.io.IOException;
+import java.util.List;
 
 public class AMSTableTestBase extends TableServiceTestBase {
   @ClassRule public static TestHMS TEST_HMS = new TestHMS();
@@ -79,15 +82,17 @@ public class AMSTableTestBase extends TableServiceTestBase {
   public void init() throws IOException, TException {
     catalogWarehouse = temp.newFolder().getPath();
     catalogMeta = catalogTestHelper.buildCatalogMeta(catalogWarehouse);
-    if (catalogTestHelper.isInternalCatalog()
-        || TableFormat.MIXED_HIVE.equals(catalogTestHelper.tableFormat())) {
-      if (TableFormat.MIXED_ICEBERG.equals(catalogTestHelper.tableFormat())
-          || TableFormat.MIXED_HIVE.equals(catalogTestHelper.tableFormat())) {
+    // mixed-hive format only exists in external catalog
+    if (catalogTestHelper.isInternalCatalog()) {
+      if (TableFormat.MIXED_ICEBERG.equals(catalogTestHelper.tableFormat())) {
         mixedTables = catalogTestHelper.buildMixedTables(catalogMeta);
         tableMeta = buildTableMeta();
       }
     } else {
       externalCatalog = new CommonUnifiedCatalog(() -> catalogMeta, 
Maps.newHashMap());
+      if (TableFormat.MIXED_HIVE.equals(catalogTestHelper.tableFormat())) {
+        tableMeta = buildTableMeta();
+      }
     }
 
     tableService().createCatalog(catalogMeta);
@@ -143,7 +148,10 @@ public class AMSTableTestBase extends TableServiceTestBase 
{
             .createDatabase(TableTestHelper.TEST_CATALOG_NAME, 
TableTestHelper.TEST_DB_NAME);
       }
     } else {
-      externalCatalog.createDatabase(TableTestHelper.TEST_DB_NAME);
+      List<String> databases = externalCatalog.listDatabases();
+      if (!(databases != null && 
databases.contains(TableTestHelper.TEST_DB_NAME))) {
+        externalCatalog.createDatabase(TableTestHelper.TEST_DB_NAME);
+      }
     }
   }
 
@@ -172,6 +180,9 @@ public class AMSTableTestBase extends TableServiceTestBase {
         case MIXED_ICEBERG:
           createMixedIcebergTable();
           break;
+        case MIXED_HIVE:
+          createMixedHiveTable();
+          break;
         default:
           throw new IllegalStateException("un-support format");
       }
@@ -181,6 +192,25 @@ public class AMSTableTestBase extends TableServiceTestBase 
{
     serverTableIdentifier = tableService().listManagedTables().get(0);
   }
 
+  private void createMixedHiveTable() {
+    // only create mixed hive table here !
+    catalogMeta.putToCatalogProperties(
+        CatalogMetaProperties.TABLE_FORMATS, TableFormat.MIXED_HIVE.name());
+    ArcticHiveCatalog catalog =
+        (ArcticHiveCatalog)
+            CatalogLoader.createCatalog(
+                catalogMeta.getCatalogName(),
+                catalogMeta.getCatalogType(),
+                catalogMeta.getCatalogProperties(),
+                ArcticCatalogUtil.buildMetaStore(catalogMeta));
+    catalog
+        .newTableBuilder(tableTestHelper.id(), tableTestHelper.tableSchema())
+        .withPartitionSpec(tableTestHelper.partitionSpec())
+        .withProperties(tableTestHelper.tableProperties())
+        .withPrimaryKeySpec(tableTestHelper.primaryKeySpec())
+        .create();
+  }
+
   private void createMixedIcebergTable() {
     ArcticCatalog catalog =
         CatalogLoader.createCatalog(
diff --git 
a/ams/server/src/test/java/com/netease/arctic/server/table/TestTableRuntimeHandler.java
 
b/ams/server/src/test/java/com/netease/arctic/server/table/TestTableRuntimeHandler.java
index d33ebde1d..ed678d176 100644
--- 
a/ams/server/src/test/java/com/netease/arctic/server/table/TestTableRuntimeHandler.java
+++ 
b/ams/server/src/test/java/com/netease/arctic/server/table/TestTableRuntimeHandler.java
@@ -66,12 +66,15 @@ public class TestTableRuntimeHandler extends 
AMSTableTestBase {
   }
 
   @Test
-  public void testInitialize() {
+  public void testInitialize() throws Exception {
     tableService = new DefaultTableService(new Configurations());
     TestHandler handler = new TestHandler();
     tableService.addHandlerChain(handler);
     tableService.initialize();
-    createDatabase();
+    if (!(catalogTestHelper().tableFormat().equals(TableFormat.MIXED_HIVE)
+        && TEST_HMS.getHiveClient().getDatabase(TableTestHelper.TEST_DB_NAME) 
!= null)) {
+      createDatabase();
+    }
     createTable();
     ServerTableIdentifier createTableId = 
tableService().listManagedTables().get(0);
     Assert.assertEquals(1, handler.getAddedTables().size());
diff --git 
a/ams/server/src/test/java/com/netease/arctic/server/table/TestTableService.java
 
b/ams/server/src/test/java/com/netease/arctic/server/table/TestTableService.java
index f5faac959..42504d5ee 100644
--- 
a/ams/server/src/test/java/com/netease/arctic/server/table/TestTableService.java
+++ 
b/ams/server/src/test/java/com/netease/arctic/server/table/TestTableService.java
@@ -70,13 +70,17 @@ public class TestTableService extends AMSTableTestBase {
 
   @Test
   public void testCreateAndDropTable() {
-    tableService().createDatabase(TEST_CATALOG_NAME, TEST_DB_NAME);
+    if (catalogTestHelper().isInternalCatalog()) {
+      tableService().createDatabase(TEST_CATALOG_NAME, TEST_DB_NAME);
+    }
 
     // test create table
     createTable();
-    Assert.assertEquals(
-        tableMeta(),
-        
tableService().loadTableMetadata(tableMeta().getTableIdentifier()).buildTableMeta());
+    if (catalogTestHelper().isInternalCatalog()) {
+      Assert.assertEquals(
+          tableMeta(),
+          
tableService().loadTableMetadata(tableMeta().getTableIdentifier()).buildTableMeta());
+    }
 
     // test list tables
     List<TableIDWithFormat> tableIdentifierList =
@@ -87,13 +91,14 @@ public class TestTableService extends AMSTableTestBase {
         tableIdentifierList.get(0).getIdentifier().buildTableIdentifier());
 
     // test list table metadata
-    List<TableMetadata> tableMetadataList = tableService().listTableMetas();
-    Assert.assertEquals(1, tableMetadataList.size());
-    Assert.assertEquals(tableMeta(), 
tableMetadataList.get(0).buildTableMeta());
-
-    tableMetadataList = tableService().listTableMetas(TEST_CATALOG_NAME, 
TEST_DB_NAME);
-    Assert.assertEquals(1, tableMetadataList.size());
-    Assert.assertEquals(tableMeta(), 
tableMetadataList.get(0).buildTableMeta());
+    if (catalogTestHelper().isInternalCatalog()) {
+      List<TableMetadata> tableMetadataList = tableService().listTableMetas();
+      Assert.assertEquals(1, tableMetadataList.size());
+      Assert.assertEquals(tableMeta(), 
tableMetadataList.get(0).buildTableMeta());
+      tableMetadataList = tableService().listTableMetas(TEST_CATALOG_NAME, 
TEST_DB_NAME);
+      Assert.assertEquals(1, tableMetadataList.size());
+      Assert.assertEquals(tableMeta(), 
tableMetadataList.get(0).buildTableMeta());
+    }
 
     // test table exist
     
Assert.assertTrue(tableService().tableExist(tableMeta().getTableIdentifier()));
@@ -148,7 +153,7 @@ public class TestTableService extends AMSTableTestBase {
         ObjectNotExistsException.class,
         () -> 
tableService().dropTableMetadata(tableMeta().getTableIdentifier(), true));
 
-    tableService().dropDatabase(TEST_CATALOG_NAME, TEST_DB_NAME);
+    dropDatabase();
   }
 
   @Test
diff --git 
a/core/src/main/java/com/netease/arctic/catalog/BasicArcticCatalog.java 
b/core/src/main/java/com/netease/arctic/catalog/BasicArcticCatalog.java
index 767b97814..7360df9a1 100644
--- a/core/src/main/java/com/netease/arctic/catalog/BasicArcticCatalog.java
+++ b/core/src/main/java/com/netease/arctic/catalog/BasicArcticCatalog.java
@@ -326,6 +326,17 @@ public class BasicArcticCatalog implements ArcticCatalog {
       return tables.createTableByMeta(tableMeta, schema, primaryKeySpec, 
partitionSpec);
     }
 
+    protected void checkAmsTableMetadata() {
+      try {
+        client.getTable(identifier.buildTableIdentifier());
+        throw new org.apache.iceberg.exceptions.AlreadyExistsException("table 
already exist");
+      } catch (NoSuchObjectException e) {
+        checkProperties();
+      } catch (TException e) {
+        throw new IllegalStateException("failed when load table", e);
+      }
+    }
+
     protected void doCreateCheck() {
       if (primaryKeySpec.primaryKeyExisted()) {
         primaryKeySpec
@@ -345,14 +356,7 @@ public class BasicArcticCatalog implements ArcticCatalog {
           .findFirst()
           .orElseThrow(() -> new 
NoSuchDatabaseException(identifier.getDatabase()));
 
-      try {
-        client.getTable(identifier.buildTableIdentifier());
-        throw new org.apache.iceberg.exceptions.AlreadyExistsException("table 
already exist");
-      } catch (NoSuchObjectException e) {
-        checkProperties();
-      } catch (TException e) {
-        throw new IllegalStateException("failed when load table", e);
-      }
+      checkAmsTableMetadata();
     }
 
     protected void checkProperties() {
diff --git a/core/src/main/java/com/netease/arctic/catalog/MixedTables.java 
b/core/src/main/java/com/netease/arctic/catalog/MixedTables.java
index 93f548fdc..9c2823ed6 100644
--- a/core/src/main/java/com/netease/arctic/catalog/MixedTables.java
+++ b/core/src/main/java/com/netease/arctic/catalog/MixedTables.java
@@ -67,6 +67,10 @@ public class MixedTables {
     this.tables = new HadoopTables(tableMetaStore.getConfiguration());
   }
 
+  public Table loadHadoopTableByLocation(String location) {
+    return tableMetaStore.doAs(() -> tables.load(location));
+  }
+
   public ArcticTable loadTableByMeta(TableMeta tableMeta) {
     if (tableMeta.getKeySpec() != null
         && tableMeta.getKeySpec().getFields() != null
diff --git 
a/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClient.java 
b/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClient.java
index feb89a197..074a81e7c 100644
--- a/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClient.java
+++ b/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClient.java
@@ -86,4 +86,6 @@ public interface HMSClient {
       EnvironmentContext environmentContext)
       throws TException, InstantiationException, IllegalAccessException, 
NoSuchMethodException,
           InvocationTargetException, ClassNotFoundException;
+
+  List<Table> getTableObjectsByName(String dbName, List<String> tableNames) 
throws TException;
 }
diff --git 
a/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClientImpl.java 
b/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClientImpl.java
index 657b27b96..37d548aec 100644
--- a/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClientImpl.java
+++ b/mixed-format/hive/src/main/java/com/netease/arctic/hive/HMSClientImpl.java
@@ -181,4 +181,10 @@ public class HMSClientImpl implements HMSClient {
             .build();
     alterPartition.invoke(getClient(), dbName, tblName, newPart, 
environmentContext);
   }
+
+  @Override
+  public List<Table> getTableObjectsByName(String dbName, List<String> 
tableNames)
+      throws TException {
+    return getClient().getTableObjectsByName(dbName, tableNames);
+  }
 }
diff --git 
a/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/ArcticHiveCatalog.java
 
b/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/ArcticHiveCatalog.java
index 2df9ba5b7..4624de98f 100644
--- 
a/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/ArcticHiveCatalog.java
+++ 
b/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/ArcticHiveCatalog.java
@@ -18,21 +18,45 @@
 
 package com.netease.arctic.hive.catalog;
 
+import static 
com.netease.arctic.properties.HiveTableProperties.ARCTIC_TABLE_PRIMARY_KEYS;
+import static 
com.netease.arctic.properties.HiveTableProperties.ARCTIC_TABLE_ROOT_LOCATION;
+import static 
com.netease.arctic.table.PrimaryKeySpec.PRIMARY_KEY_COLUMN_JOIN_DELIMITER;
+import static 
com.netease.arctic.table.TableProperties.LOG_STORE_STORAGE_TYPE_KAFKA;
+import static 
com.netease.arctic.table.TableProperties.LOG_STORE_STORAGE_TYPE_PULSAR;
+import static com.netease.arctic.table.TableProperties.LOG_STORE_TYPE;
+
+import com.netease.arctic.AmsClient;
+import com.netease.arctic.NoSuchDatabaseException;
+import com.netease.arctic.PooledAmsClient;
 import com.netease.arctic.TableFormat;
 import com.netease.arctic.api.TableMeta;
-import com.netease.arctic.catalog.BasicArcticCatalog;
-import com.netease.arctic.catalog.MixedTables;
+import com.netease.arctic.catalog.ArcticCatalog;
 import com.netease.arctic.hive.CachedHiveClientPool;
 import com.netease.arctic.hive.HMSClient;
 import com.netease.arctic.hive.HMSClientPool;
+import com.netease.arctic.hive.utils.CompatibleHivePropertyUtil;
 import com.netease.arctic.hive.utils.HiveSchemaUtil;
+import com.netease.arctic.hive.utils.HiveTableUtil;
+import com.netease.arctic.io.ArcticFileIO;
+import com.netease.arctic.io.ArcticFileIOs;
+import com.netease.arctic.op.ArcticHadoopTableOperations;
+import com.netease.arctic.op.CreateTableTransaction;
+import com.netease.arctic.properties.CatalogMetaProperties;
 import com.netease.arctic.properties.HiveTableProperties;
+import com.netease.arctic.properties.MetaTableProperties;
+import com.netease.arctic.table.ArcticTable;
 import com.netease.arctic.table.PrimaryKeySpec;
 import com.netease.arctic.table.TableBuilder;
 import com.netease.arctic.table.TableIdentifier;
 import com.netease.arctic.table.TableMetaStore;
 import com.netease.arctic.table.TableProperties;
+import com.netease.arctic.table.blocker.BasicTableBlockerManager;
+import com.netease.arctic.table.blocker.TableBlockerManager;
+import com.netease.arctic.utils.ArcticCatalogUtil;
+import com.netease.arctic.utils.CompatiblePropertyUtil;
 import com.netease.arctic.utils.ConvertStructUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
 import org.apache.hadoop.hive.metastore.api.Database;
 import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
@@ -41,33 +65,64 @@ import org.apache.iceberg.PartitionField;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.Table;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableOperations;
+import org.apache.iceberg.Transaction;
+import org.apache.iceberg.Transactions;
+import org.apache.iceberg.exceptions.NoSuchTableException;
 import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * Implementation of {@link com.netease.arctic.catalog.ArcticCatalog} to 
support Hive table as base
  * store.
  */
-public class ArcticHiveCatalog extends BasicArcticCatalog {
+public class ArcticHiveCatalog implements ArcticCatalog {
 
   private static final Logger LOG = 
LoggerFactory.getLogger(ArcticHiveCatalog.class);
 
+  protected AmsClient client;
   private CachedHiveClientPool hiveClientPool;
+  protected String name;
+  protected Map<String, String> catalogProperties;
+  protected MixedHiveTables tables;
+  protected transient TableMetaStore tableMetaStore;
+
+  @Override
+  public String name() {
+    return name;
+  }
 
   @Override
   public void initialize(String name, Map<String, String> properties, 
TableMetaStore metaStore) {
-    super.initialize(name, properties, metaStore);
+    if (properties.get(CatalogMetaProperties.AMS_URI) != null) {
+      this.client = new 
PooledAmsClient(properties.get(CatalogMetaProperties.AMS_URI));
+    }
+    this.name = name;
+    this.catalogProperties = properties;
+    this.tableMetaStore = metaStore;
+    this.tables = newMixedHiveTables(properties, metaStore);
     this.hiveClientPool = ((MixedHiveTables) tables).getHiveClientPool();
   }
 
-  @Override
-  protected MixedTables newMixedTables(
+  protected MixedHiveTables getTables() {
+    return tables;
+  }
+
+  protected MixedHiveTables newMixedHiveTables(
       Map<String, String> catalogProperties, TableMetaStore metaStore) {
     return new MixedHiveTables(catalogProperties, metaStore);
   }
@@ -100,10 +155,93 @@ public class ArcticHiveCatalog extends BasicArcticCatalog 
{
     }
   }
 
-  /** HMS is case-insensitive for table name and database */
   @Override
+  public TableBlockerManager getTableBlockerManager(TableIdentifier 
tableIdentifier) {
+    validate(tableIdentifier);
+    return BasicTableBlockerManager.build(tableIdentifier, client);
+  }
+
+  @Override
+  public Map<String, String> properties() {
+    return catalogProperties;
+  }
+
+  public static void putNotNullProperties(
+      Map<String, String> properties, String key, String value) {
+    if (value != null) {
+      properties.put(key, value);
+    }
+  }
+
+  /** HMS is case-insensitive for table name and database */
   protected TableMeta getArcticTableMeta(TableIdentifier identifier) {
-    return super.getArcticTableMeta(identifier.toLowCaseIdentifier());
+    org.apache.hadoop.hive.metastore.api.Table hiveTable = null;
+    identifier = identifier.toLowCaseIdentifier();
+    try {
+      hiveTable = HiveTableUtil.loadHmsTable(this.hiveClientPool, identifier);
+    } catch (RuntimeException e) {
+      throw new IllegalStateException(String.format("failed load hive table 
%s.", identifier), e);
+    }
+    if (hiveTable == null) {
+      throw new NoSuchTableException("load table failed %s.", identifier);
+    }
+
+    Map<String, String> hiveParameters = hiveTable.getParameters();
+
+    String arcticRootLocation = hiveParameters.get(ARCTIC_TABLE_ROOT_LOCATION);
+    if (arcticRootLocation == null) {
+      // if hive location ends with /hive, then it's a mixed-hive table. we 
need to remove /hive to
+      // get root location.
+      // if hive location doesn't end with /hive, then it's a pure-hive table. 
we can use the
+      // location as root location.
+      String hiveRootLocation = hiveTable.getSd().getLocation();
+      if (hiveRootLocation.endsWith("/hive")) {
+        arcticRootLocation = hiveRootLocation.substring(0, 
hiveRootLocation.length() - 5);
+      } else {
+        arcticRootLocation = hiveRootLocation;
+      }
+    }
+
+    // full path of base, change and root location
+    String baseLocation = arcticRootLocation + "/base";
+    String changeLocation = arcticRootLocation + "/change";
+    // load base table for get arctic table properties
+    Table baseIcebergTable = 
getTables().loadHadoopTableByLocation(baseLocation);
+    if (baseIcebergTable == null) {
+      throw new NoSuchTableException("load table failed %s, base table not 
found.", identifier);
+    }
+    Map<String, String> properties = baseIcebergTable.properties();
+    // start to construct TableMeta
+    TableMeta tableMeta = new TableMeta();
+    tableMeta.setTableIdentifier(identifier.buildTableIdentifier());
+
+    Map<String, String> locations = new HashMap<>();
+    putNotNullProperties(locations, MetaTableProperties.LOCATION_KEY_TABLE, 
arcticRootLocation);
+    putNotNullProperties(locations, MetaTableProperties.LOCATION_KEY_CHANGE, 
changeLocation);
+    putNotNullProperties(locations, MetaTableProperties.LOCATION_KEY_BASE, 
baseLocation);
+    // set table location
+    tableMeta.setLocations(locations);
+
+    // set table properties
+    Map<String, String> newProperties = new HashMap<>(properties);
+    tableMeta.setProperties(newProperties);
+
+    // set table's primary key when needed
+    if (hiveParameters != null) {
+      String primaryKey = hiveParameters.get(ARCTIC_TABLE_PRIMARY_KEYS);
+      // primary key info come from hive properties
+      if (StringUtils.isNotBlank(primaryKey)) {
+        com.netease.arctic.api.PrimaryKeySpec keySpec = new 
com.netease.arctic.api.PrimaryKeySpec();
+        List<String> fields =
+            Arrays.stream(primaryKey.split(PRIMARY_KEY_COLUMN_JOIN_DELIMITER))
+                .collect(Collectors.toList());
+        keySpec.setFields(fields);
+        tableMeta.setKeySpec(keySpec);
+      }
+    }
+    // set table format to mixed-hive format
+    tableMeta.setFormat(TableFormat.MIXED_HIVE.name());
+    return tableMeta;
   }
 
   @Override
@@ -130,26 +268,258 @@ public class ArcticHiveCatalog extends 
BasicArcticCatalog {
     return new MixedHiveTableBuilder(identifier, schema);
   }
 
+  @Override
+  public void renameTable(TableIdentifier from, String newTableName) {
+    throw new UnsupportedOperationException("unsupported rename arctic table 
for now.");
+  }
+
   public HMSClientPool getHMSClient() {
     return hiveClientPool;
   }
 
-  class MixedHiveTableBuilder extends ArcticTableBuilder {
+  /**
+   *
+   *
+   * <ul>
+   *   <li>1、call getTableObjectsByName to get all Table objects of database
+   *   <li>2、filter hive tables whose properties don't have arctic table flag
+   * </ul>
+   *
+   * we don't do cache here because we create/drop table through engine (like 
spark) connector, they
+   * have another ArcticHiveCatalog instance。 we can't find a easy way to 
update cache.
+   *
+   * @param database
+   * @return
+   */
+  @Override
+  public List<TableIdentifier> listTables(String database) {
+    final List<TableIdentifier> result = new ArrayList<>();
+    try {
+      hiveClientPool.run(
+          client -> {
+            List<String> tableNames = client.getAllTables(database);
+            long start = System.currentTimeMillis();
+            List<org.apache.hadoop.hive.metastore.api.Table> hiveTables =
+                client.getTableObjectsByName(database, tableNames);
+            LOG.info("call getTableObjectsByName cost {} ms", 
System.currentTimeMillis() - start);
+            // filter hive tables whose properties don't have arctic table flag
+            if (hiveTables != null && !hiveTables.isEmpty()) {
+              List<TableIdentifier> loadResult =
+                  hiveTables.stream()
+                      .filter(
+                          table ->
+                              table.getParameters() != null
+                                  && 
CompatibleHivePropertyUtil.propertyAsBoolean(
+                                      table.getParameters(),
+                                      HiveTableProperties.ARCTIC_TABLE_FLAG,
+                                      false))
+                      .map(table -> TableIdentifier.of(name(), database, 
table.getTableName()))
+                      .collect(Collectors.toList());
+              if (loadResult != null && !loadResult.isEmpty()) {
+                result.addAll(loadResult);
+              }
+              LOG.debug(
+                  "load {} tables from database {} of catalog {}",
+                  loadResult == null ? 0 : loadResult.size(),
+                  database,
+                  name());
+            } else {
+              LOG.debug("load no tables from database {} of catalog {}", 
database, name());
+            }
+            return result;
+          });
+    } catch (NoSuchObjectException e) {
+      // pass
+    } catch (TException | InterruptedException e) {
+      throw new RuntimeException("Failed to listTables of database :" + 
database, e);
+    }
+    return result;
+  }
+
+  private void validate(TableIdentifier identifier) {
+    if (StringUtils.isNotBlank(identifier.getCatalog())) {
+      identifier.setCatalog(this.name());
+    } else if (!this.name().equals(identifier.getCatalog())) {
+      throw new IllegalArgumentException("catalog name miss match");
+    }
+  }
+
+  @Override
+  public ArcticTable loadTable(TableIdentifier identifier) {
+    validate(identifier);
+    TableMeta meta = getArcticTableMeta(identifier);
+    if (meta.getLocations() == null) {
+      throw new IllegalStateException("load table failed, lack locations 
info");
+    }
+    return tables.loadTableByMeta(meta);
+  }
+
+  @Override
+  public boolean dropTable(TableIdentifier identifier, boolean purge) {
+    validate(identifier);
+    TableMeta meta;
+    try {
+      meta = getArcticTableMeta(identifier);
+    } catch (NoSuchTableException e) {
+      return false;
+    }
+
+    doDropTable(meta, purge);
+    return true;
+  }
+
+  protected void doDropTable(TableMeta meta, boolean purge) {
+    tables.dropTableByMeta(meta, purge);
+  }
+
+  class MixedHiveTableBuilder implements TableBuilder {
+    protected TableIdentifier identifier;
+    protected Schema schema;
+    protected PartitionSpec partitionSpec;
+    protected SortOrder sortOrder;
+    protected Map<String, String> properties = new HashMap<>();
+    protected PrimaryKeySpec primaryKeySpec = PrimaryKeySpec.noPrimaryKey();
+    protected String location;
+
+    @Override
+    public ArcticTable create() {
+      ConvertStructUtil.TableMetaBuilder builder = createTableMataBuilder();
+      doCreateCheck();
+      TableMeta meta = builder.build();
+      ArcticTable table = createTableByMeta(meta, schema, primaryKeySpec, 
partitionSpec);
+      return table;
+    }
+
+    @Override
+    public Transaction createTransaction() {
+      ArcticFileIO arcticFileIO = 
ArcticFileIOs.buildHadoopFileIO(tableMetaStore);
+      ConvertStructUtil.TableMetaBuilder builder = createTableMataBuilder();
+      TableMeta meta = builder.build();
+      String location = getTableLocationForCreate();
+      TableOperations tableOperations =
+          new ArcticHadoopTableOperations(
+              new Path(location), arcticFileIO, 
tableMetaStore.getConfiguration());
+      TableMetadata tableMetadata =
+          tableMetadata(schema, partitionSpec, sortOrder, properties, 
location);
+      Transaction transaction =
+          Transactions.createTableTransaction(
+              identifier.getTableName(), tableOperations, tableMetadata);
+      return new CreateTableTransaction(
+          transaction,
+          this::create,
+          () -> {
+            doRollbackCreateTable(meta);
+            try {
+              client.removeTable(identifier.buildTableIdentifier(), true);
+            } catch (TException e) {
+              throw new RuntimeException(e);
+            }
+          });
+    }
+
+    protected ArcticTable createTableByMeta(
+        TableMeta tableMeta,
+        Schema schema,
+        PrimaryKeySpec primaryKeySpec,
+        PartitionSpec partitionSpec) {
+      return tables.createTableByMeta(tableMeta, schema, primaryKeySpec, 
partitionSpec);
+    }
+
+    protected void checkProperties() {
+      Map<String, String> mergedProperties =
+          ArcticCatalogUtil.mergeCatalogPropertiesToTable(properties, 
catalogProperties);
+      boolean enableStream =
+          CompatiblePropertyUtil.propertyAsBoolean(
+              mergedProperties,
+              TableProperties.ENABLE_LOG_STORE,
+              TableProperties.ENABLE_LOG_STORE_DEFAULT);
+      if (enableStream) {
+        Preconditions.checkArgument(
+            
mergedProperties.containsKey(TableProperties.LOG_STORE_MESSAGE_TOPIC),
+            "log-store.topic must not be null when log-store.enabled is 
true.");
+        Preconditions.checkArgument(
+            mergedProperties.containsKey(TableProperties.LOG_STORE_ADDRESS),
+            "log-store.address must not be null when log-store.enabled is 
true.");
+        String logStoreType = mergedProperties.get(LOG_STORE_TYPE);
+        Preconditions.checkArgument(
+            logStoreType == null
+                || logStoreType.equals(LOG_STORE_STORAGE_TYPE_KAFKA)
+                || logStoreType.equals(LOG_STORE_STORAGE_TYPE_PULSAR),
+            String.format(
+                "%s can not be set %s, valid values are: [%s, %s].",
+                LOG_STORE_TYPE,
+                logStoreType,
+                LOG_STORE_STORAGE_TYPE_KAFKA,
+                LOG_STORE_STORAGE_TYPE_PULSAR));
+        properties.putIfAbsent(
+            TableProperties.LOG_STORE_DATA_FORMAT, 
TableProperties.LOG_STORE_DATA_FORMAT_DEFAULT);
+      }
+    }
+
+    private String getTableLocationForCreate() {
+      if (StringUtils.isNotBlank(location)) {
+        return location;
+      }
+
+      if (properties.containsKey(TableProperties.LOCATION)) {
+        String tableLocation = properties.get(TableProperties.LOCATION);
+        if (!Objects.equals("/", tableLocation) && 
tableLocation.endsWith("/")) {
+          tableLocation = tableLocation.substring(0, tableLocation.length() - 
1);
+        }
+        if (StringUtils.isNotBlank(tableLocation)) {
+          return tableLocation;
+        }
+      }
+
+      String databaseLocation = getDatabaseLocation();
+
+      if (StringUtils.isNotBlank(databaseLocation)) {
+        return databaseLocation + '/' + identifier.getTableName();
+      } else {
+        throw new IllegalStateException(
+            "either `location` in table properties or "
+                + "`warehouse` in catalog properties is specified");
+      }
+    }
+
+    protected TableMetadata tableMetadata(
+        Schema schema,
+        PartitionSpec spec,
+        SortOrder order,
+        Map<String, String> properties,
+        String location) {
+      Preconditions.checkNotNull(schema, "A table schema is required");
+
+      Map<String, String> tableProps = properties == null ? ImmutableMap.of() 
: properties;
+      PartitionSpec partitionSpec = spec == null ? 
PartitionSpec.unpartitioned() : spec;
+      SortOrder sortOrder = order == null ? SortOrder.unsorted() : order;
+      return TableMetadata.newTableMetadata(schema, partitionSpec, sortOrder, 
location, tableProps);
+    }
 
     public MixedHiveTableBuilder(TableIdentifier identifier, Schema schema) {
-      super(identifier.toLowCaseIdentifier(), 
HiveSchemaUtil.changeFieldNameToLowercase(schema));
+      Preconditions.checkArgument(
+          identifier.getCatalog().equals(name()),
+          "Illegal table id:%s for catalog:%s",
+          identifier.toString(),
+          name());
+      this.identifier = identifier.toLowCaseIdentifier();
+      this.schema = HiveSchemaUtil.changeFieldNameToLowercase(schema);
+      this.partitionSpec = PartitionSpec.unpartitioned();
+      this.sortOrder = SortOrder.unsorted();
     }
 
     boolean allowExistedHiveTable = false;
 
     @Override
     public TableBuilder withPartitionSpec(PartitionSpec partitionSpec) {
-      return 
super.withPartitionSpec(IcebergSchemaUtil.copyPartitionSpec(partitionSpec, 
schema));
+      this.partitionSpec = IcebergSchemaUtil.copyPartitionSpec(partitionSpec, 
schema);
+      return this;
     }
 
     @Override
     public TableBuilder withSortOrder(SortOrder sortOrder) {
-      return 
super.withSortOrder(IcebergSchemaUtil.copySortOrderSpec(sortOrder, schema));
+      this.sortOrder = IcebergSchemaUtil.copySortOrderSpec(sortOrder, schema);
+      return this;
     }
 
     @Override
@@ -160,18 +530,19 @@ public class ArcticHiveCatalog extends BasicArcticCatalog 
{
           .forEach(
               primaryKeyField ->
                   
builder.addColumn(primaryKeyField.fieldName().toLowerCase(Locale.ROOT)));
-      return super.withPrimaryKeySpec(builder.build());
+      this.primaryKeySpec = builder.build();
+      return this;
     }
 
     @Override
     public TableBuilder withProperty(String key, String value) {
       if (key.equals(HiveTableProperties.ALLOW_HIVE_TABLE_EXISTED) && 
value.equals("true")) {
         allowExistedHiveTable = true;
-        super.withProperty(key, value);
+        this.properties.put(key, value);
       } else if (key.equals(TableProperties.TABLE_EVENT_TIME_FIELD)) {
-        super.withProperty(key, value.toLowerCase(Locale.ROOT));
+        this.properties.put(key, value.toLowerCase(Locale.ROOT));
       } else {
-        super.withProperty(key, value);
+        this.properties.put(key, value);
       }
       return this;
     }
@@ -182,17 +553,40 @@ public class ArcticHiveCatalog extends BasicArcticCatalog 
{
       return this;
     }
 
-    @Override
     protected void doCreateCheck() {
+      if (primaryKeySpec.primaryKeyExisted()) {
+        primaryKeySpec
+            .fieldNames()
+            .forEach(
+                primaryKey -> {
+                  if (schema.findField(primaryKey).isOptional()) {
+                    throw new IllegalArgumentException(
+                        "please check your schema, the primary key nested 
field must"
+                            + " be required and field name is "
+                            + primaryKey);
+                  }
+                });
+      }
+      listDatabases().stream()
+          .filter(d -> d.equals(identifier.getDatabase()))
+          .findFirst()
+          .orElseThrow(() -> new 
NoSuchDatabaseException(identifier.getDatabase()));
 
-      super.doCreateCheck();
       try {
+        org.apache.hadoop.hive.metastore.api.Table hiveTable =
+            hiveClientPool.run(
+                client -> client.getTable(identifier.getDatabase(), 
identifier.getTableName()));
+        if (hiveTable != null) {
+          // do some check for whether the table has been upgraded!!!
+          if (CompatibleHivePropertyUtil.propertyAsBoolean(
+              hiveTable.getParameters(), 
HiveTableProperties.ARCTIC_TABLE_FLAG, false)) {
+            throw new IllegalArgumentException(
+                String.format("Table %s has already been upgraded !", 
identifier));
+          }
+        }
         if (allowExistedHiveTable) {
           LOG.info("No need to check hive table exist");
         } else {
-          org.apache.hadoop.hive.metastore.api.Table hiveTable =
-              hiveClientPool.run(
-                  client -> client.getTable(identifier.getDatabase(), 
identifier.getTableName()));
           if (hiveTable != null) {
             throw new IllegalArgumentException(
                 "Table is already existed in hive meta store:" + identifier);
@@ -215,9 +609,10 @@ public class ArcticHiveCatalog extends BasicArcticCatalog {
               "Partition field should be at last of " + "schema");
         }
       }
+
+      checkProperties();
     }
 
-    @Override
     protected String getDatabaseLocation() {
       try {
         return hiveClientPool.run(
@@ -228,7 +623,6 @@ public class ArcticHiveCatalog extends BasicArcticCatalog {
       }
     }
 
-    @Override
     protected void doRollbackCreateTable(TableMeta meta) {
       if (allowExistedHiveTable) {
         LOG.info(
@@ -237,13 +631,28 @@ public class ArcticHiveCatalog extends BasicArcticCatalog 
{
             meta.getTableIdentifier().getTableName());
         tables.dropTableByMeta(meta, false);
       } else {
-        super.doRollbackCreateTable(meta);
+        tables.dropTableByMeta(meta, true);
       }
     }
 
-    @Override
     protected ConvertStructUtil.TableMetaBuilder createTableMataBuilder() {
-      ConvertStructUtil.TableMetaBuilder builder = 
super.createTableMataBuilder();
+      ConvertStructUtil.TableMetaBuilder builder =
+          ConvertStructUtil.newTableMetaBuilder(this.identifier, this.schema);
+      String tableLocation = getTableLocationForCreate();
+
+      builder
+          .withTableLocation(tableLocation)
+          .withProperties(this.properties)
+          .withPrimaryKeySpec(this.primaryKeySpec);
+
+      if (this.primaryKeySpec.primaryKeyExisted()) {
+        builder =
+            builder
+                .withBaseLocation(tableLocation + "/base")
+                .withChangeLocation(tableLocation + "/change");
+      } else {
+        builder = builder.withBaseLocation(tableLocation + "/base");
+      }
       return builder.withFormat(TableFormat.MIXED_HIVE);
     }
   }
diff --git 
a/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/MixedHiveTables.java
 
b/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/MixedHiveTables.java
index 5fcd8a8ed..1343fd0af 100644
--- 
a/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/MixedHiveTables.java
+++ 
b/mixed-format/hive/src/main/java/com/netease/arctic/hive/catalog/MixedHiveTables.java
@@ -19,7 +19,6 @@
 package com.netease.arctic.hive.catalog;
 
 import com.netease.arctic.api.TableMeta;
-import com.netease.arctic.catalog.MixedTables;
 import com.netease.arctic.hive.CachedHiveClientPool;
 import com.netease.arctic.hive.table.KeyedHiveTable;
 import com.netease.arctic.hive.table.UnkeyedHiveTable;
@@ -28,8 +27,10 @@ import com.netease.arctic.hive.utils.HiveTableUtil;
 import com.netease.arctic.io.ArcticFileIO;
 import com.netease.arctic.io.ArcticFileIOs;
 import com.netease.arctic.io.ArcticHadoopFileIO;
+import com.netease.arctic.io.TableTrashManagers;
 import com.netease.arctic.properties.HiveTableProperties;
 import com.netease.arctic.properties.MetaTableProperties;
+import com.netease.arctic.table.ArcticTable;
 import com.netease.arctic.table.ChangeTable;
 import com.netease.arctic.table.KeyedTable;
 import com.netease.arctic.table.PrimaryKeySpec;
@@ -37,36 +38,66 @@ import com.netease.arctic.table.TableIdentifier;
 import com.netease.arctic.table.TableMetaStore;
 import com.netease.arctic.table.TableProperties;
 import com.netease.arctic.utils.ArcticCatalogUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.hive.metastore.TableType;
 import org.apache.iceberg.FileFormat;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.Table;
+import org.apache.iceberg.Tables;
 import org.apache.iceberg.exceptions.NoSuchTableException;
+import org.apache.iceberg.hadoop.HadoopTables;
 import org.apache.iceberg.mapping.MappingUtil;
 import org.apache.iceberg.mapping.NameMappingParser;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
 import org.apache.iceberg.relocated.com.google.common.collect.Maps;
 import org.apache.iceberg.util.PropertyUtil;
 import org.apache.thrift.TException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
-public class MixedHiveTables extends MixedTables {
+public class MixedHiveTables {
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(MixedHiveTables.class);
+
+  protected Tables tables;
+  protected TableMetaStore tableMetaStore;
+  protected Map<String, String> catalogProperties;
   private volatile CachedHiveClientPool hiveClientPool;
 
   public MixedHiveTables(Map<String, String> catalogProperties, TableMetaStore 
metaStore) {
-    super(catalogProperties, metaStore);
+    this.tableMetaStore = metaStore;
+    this.catalogProperties = catalogProperties;
+    this.tables = new HadoopTables(tableMetaStore.getConfiguration());
     this.hiveClientPool = new CachedHiveClientPool(getTableMetaStore(), 
catalogProperties);
   }
 
+  protected TableMetaStore getTableMetaStore() {
+    return tableMetaStore;
+  }
+
   public CachedHiveClientPool getHiveClientPool() {
     return hiveClientPool;
   }
 
-  @Override
+  public Table loadHadoopTableByLocation(String location) {
+    return tableMetaStore.doAs(() -> tables.load(location));
+  }
+
+  public ArcticTable loadTableByMeta(TableMeta tableMeta) {
+    if (tableMeta.getKeySpec() != null
+        && tableMeta.getKeySpec().getFields() != null
+        && tableMeta.getKeySpec().getFields().size() > 0) {
+      return loadKeyedTable(tableMeta);
+    } else {
+      return loadUnKeyedTable(tableMeta);
+    }
+  }
+
   protected KeyedHiveTable loadKeyedTable(TableMeta tableMeta) {
     TableIdentifier tableIdentifier = 
TableIdentifier.of(tableMeta.getTableIdentifier());
     String tableLocation = checkLocation(tableMeta, 
MetaTableProperties.LOCATION_KEY_TABLE);
@@ -120,7 +151,6 @@ public class MixedHiveTables extends MixedTables {
     }
   }
 
-  @Override
   protected UnkeyedHiveTable loadUnKeyedTable(TableMeta tableMeta) {
     TableIdentifier tableIdentifier = 
TableIdentifier.of(tableMeta.getTableIdentifier());
     String baseLocation = checkLocation(tableMeta, 
MetaTableProperties.LOCATION_KEY_BASE);
@@ -144,7 +174,6 @@ public class MixedHiveTables extends MixedTables {
         catalogProperties);
   }
 
-  @Override
   protected KeyedTable createKeyedTable(
       TableMeta tableMeta,
       Schema schema,
@@ -262,7 +291,6 @@ public class MixedHiveTables extends MixedTables {
         tableMeta, tableLocation, primaryKeySpec, hiveClientPool, baseTable, 
changeTable);
   }
 
-  @Override
   protected UnkeyedHiveTable createUnKeyedTable(
       TableMeta tableMeta,
       Schema schema,
@@ -346,9 +374,68 @@ public class MixedHiveTables extends MixedTables {
         catalogProperties);
   }
 
-  @Override
+  public void dropInternalTableByMeta(TableMeta tableMeta, boolean purge) {
+    try {
+      ArcticFileIO fileIO = ArcticFileIOs.buildHadoopFileIO(tableMetaStore);
+      Map<String, String> tableProperties = Maps.newHashMap();
+      try {
+        ArcticTable arcticTable = loadTableByMeta(tableMeta);
+        tableProperties.putAll(arcticTable.properties());
+      } catch (Exception loadException) {
+        LOG.warn("load table failed when dropping table", loadException);
+      }
+
+      // If purge is true, all manifest/data files must be located under the 
table directory.
+      if (!purge) {
+        String baseLocation = 
tableMeta.getLocations().get(MetaTableProperties.LOCATION_KEY_BASE);
+        String changeLocation =
+            
tableMeta.getLocations().get(MetaTableProperties.LOCATION_KEY_CHANGE);
+        try {
+          if (StringUtils.isNotBlank(baseLocation)) {
+            dropInternalTable(tableMetaStore, baseLocation, false);
+          }
+          if (StringUtils.isNotBlank(changeLocation)) {
+            dropInternalTable(tableMetaStore, changeLocation, false);
+          }
+        } catch (Exception e) {
+          LOG.warn("drop base/change iceberg table fail ", e);
+        }
+      } else {
+        String tableLocation = 
tableMeta.getLocations().get(MetaTableProperties.LOCATION_KEY_TABLE);
+        if (fileIO.exists(tableLocation)) {
+          LOG.info("try to delete table directory location is " + 
tableLocation);
+          fileIO.asPrefixFileIO().deletePrefix(tableLocation);
+        }
+      }
+
+      // delete custom trash location
+      String customTrashLocation =
+          
tableProperties.get(TableProperties.TABLE_TRASH_CUSTOM_ROOT_LOCATION);
+      if (customTrashLocation != null) {
+        TableIdentifier tableId = 
TableIdentifier.of(tableMeta.getTableIdentifier());
+        String trashParentLocation =
+            TableTrashManagers.getTrashParentLocation(tableId, 
customTrashLocation);
+        if (fileIO.exists(trashParentLocation)) {
+          fileIO.asPrefixFileIO().deletePrefix(trashParentLocation);
+        }
+      }
+    } catch (Exception e) {
+      LOG.warn("drop table directory fail ", e);
+    }
+  }
+
+  private void dropInternalTable(
+      TableMetaStore tableMetaStore, String internalTableLocation, boolean 
purge) {
+    final HadoopTables internalTables = new 
HadoopTables(tableMetaStore.getConfiguration());
+    tableMetaStore.doAs(
+        () -> {
+          internalTables.dropTable(internalTableLocation, purge);
+          return null;
+        });
+  }
+
   public void dropTableByMeta(TableMeta tableMeta, boolean purge) {
-    super.dropTableByMeta(tableMeta, purge);
+    dropInternalTableByMeta(tableMeta, purge);
     if (!HiveTableUtil.checkExist(
         hiveClientPool, TableIdentifier.of(tableMeta.getTableIdentifier()))) {
       // If hive table does not exist, we will not try to drop hive table
@@ -397,7 +484,12 @@ public class MixedHiveTables extends MixedTables {
   }
 
   protected void fillTableProperties(TableMeta meta) {
-    super.fillTableProperties(meta);
+    meta.putToProperties(
+        TableProperties.TABLE_CREATE_TIME, 
String.valueOf(System.currentTimeMillis()));
+    meta.putToProperties(org.apache.iceberg.TableProperties.FORMAT_VERSION, 
"2");
+    meta.putToProperties(
+        
org.apache.iceberg.TableProperties.METADATA_DELETE_AFTER_COMMIT_ENABLED, 
"true");
+    meta.putToProperties("flink.max-continuous-empty-commits", 
String.valueOf(Integer.MAX_VALUE));
     String tableLocation = checkLocation(meta, 
MetaTableProperties.LOCATION_KEY_TABLE);
     String hiveLocation = HiveTableUtil.hiveRootLocation(tableLocation);
     meta.putToProperties(HiveTableProperties.BASE_HIVE_LOCATION_ROOT, 
hiveLocation);
@@ -455,4 +547,34 @@ public class MixedHiveTables extends MixedTables {
         
tableMeta.getProperties().remove(HiveTableProperties.ALLOW_HIVE_TABLE_EXISTED);
     return Boolean.parseBoolean(allowStringValue);
   }
+
+  public ArcticTable createTableByMeta(
+      TableMeta tableMeta,
+      Schema schema,
+      PrimaryKeySpec primaryKeySpec,
+      PartitionSpec partitionSpec) {
+    if (primaryKeySpec.primaryKeyExisted()) {
+      return createKeyedTable(tableMeta, schema, primaryKeySpec, 
partitionSpec);
+    } else {
+      return createUnKeyedTable(tableMeta, schema, primaryKeySpec, 
partitionSpec);
+    }
+  }
+
+  protected String checkLocation(TableMeta meta, String locationKey) {
+    String location = meta.getLocations().get(locationKey);
+    Preconditions.checkArgument(StringUtils.isNotBlank(location), "table 
location can't found");
+    return location;
+  }
+
+  protected PrimaryKeySpec buildPrimaryKeySpec(Schema schema, TableMeta 
tableMeta) {
+    PrimaryKeySpec.Builder builder = PrimaryKeySpec.builderFor(schema);
+    if (tableMeta.getKeySpec() != null
+        && tableMeta.getKeySpec().getFields() != null
+        && !tableMeta.getKeySpec().getFields().isEmpty()) {
+      for (String field : tableMeta.getKeySpec().getFields()) {
+        builder.addColumn(field);
+      }
+    }
+    return builder.build();
+  }
 }
diff --git 
a/mixed-format/hive/src/test/java/com/netease/arctic/hive/catalog/HiveCatalogTestHelper.java
 
b/mixed-format/hive/src/test/java/com/netease/arctic/hive/catalog/HiveCatalogTestHelper.java
index 6e4358c17..526a14440 100644
--- 
a/mixed-format/hive/src/test/java/com/netease/arctic/hive/catalog/HiveCatalogTestHelper.java
+++ 
b/mixed-format/hive/src/test/java/com/netease/arctic/hive/catalog/HiveCatalogTestHelper.java
@@ -73,6 +73,9 @@ public class HiveCatalogTestHelper implements 
CatalogTestHelper {
 
   @Override
   public UnifiedCatalog buildUnifiedCatalog(CatalogMeta catalogMeta) {
+    catalogMeta
+        .getCatalogProperties()
+        .put(CatalogMetaProperties.TABLE_FORMATS, 
TableFormat.MIXED_HIVE.name());
     return new CommonUnifiedCatalog(() -> catalogMeta, Maps.newHashMap());
   }
 
@@ -90,7 +93,7 @@ public class HiveCatalogTestHelper implements 
CatalogTestHelper {
       throw new UnsupportedOperationException(
           "Cannot build mixed-tables for table format:" + tableFormat);
     }
-    return new MixedHiveTables(
+    return new MixedTables(
         catalogMeta.getCatalogProperties(), 
ArcticCatalogUtil.buildMetaStore(catalogMeta));
   }
 
diff --git 
a/mixed-format/spark/v3.2/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
 
b/mixed-format/spark/v3.2/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
index 6356ef130..3f41ad620 100644
--- 
a/mixed-format/spark/v3.2/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
+++ 
b/mixed-format/spark/v3.2/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
@@ -25,6 +25,7 @@ import com.netease.arctic.spark.sql.execution
 import org.apache.spark.sql.SparkSessionExtensions
 import 
org.apache.spark.sql.catalyst.analysis.{AlignedRowLevelIcebergCommandCheck, 
AlignRowLevelCommandAssignments, CheckMergeIntoTableConditions, 
MergeIntoIcebergTableResolutionCheck, ProcedureArgumentCoercion, 
ResolveMergeIntoTableReferences, ResolveProcedures, RewriteDeleteFromTable, 
RewriteMergeIntoTable, RewriteUpdateTable}
 import org.apache.spark.sql.catalyst.optimizer._
+import 
org.apache.spark.sql.catalyst.parser.extensions.IcebergSparkSqlExtensionsParser
 import 
org.apache.spark.sql.execution.datasources.v2.{ExtendedDataSourceV2Strategy, 
ExtendedV2Writes, OptimizeMetadataOnlyDeleteFromTable, 
ReplaceRewrittenRowLevelCommand, RowLevelCommandScanRelationPushDown}
 import 
org.apache.spark.sql.execution.dynamicpruning.RowLevelCommandDynamicPruning
 
@@ -74,6 +75,12 @@ class ArcticSparkExtensions extends (SparkSessionExtensions 
=> Unit) {
 
     // arctic strategy rules
     extensions.injectPlannerStrategy { spark => 
execution.ExtendedArcticStrategy(spark) }
+
+    // iceberg sql parser extensions
+    extensions.injectParser { case (_, parser) => new 
IcebergSparkSqlExtensionsParser(parser) }
+
+    // iceberg procedure analyzer extensions
+    extensions.injectResolutionRule { spark => ResolveProcedures(spark) }
   }
 
 }
diff --git 
a/mixed-format/spark/v3.3/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
 
b/mixed-format/spark/v3.3/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
index 95864babb..6a438f466 100644
--- 
a/mixed-format/spark/v3.3/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
+++ 
b/mixed-format/spark/v3.3/spark/src/main/scala/com/netease/arctic/spark/ArcticSparkExtensions.scala
@@ -26,6 +26,7 @@ import com.netease.arctic.spark.sql.execution
 import org.apache.spark.sql.SparkSessionExtensions
 import 
org.apache.spark.sql.catalyst.analysis.{AlignedRowLevelIcebergCommandCheck, 
AlignRowLevelCommandAssignments, CheckMergeIntoTableConditions, 
MergeIntoIcebergTableResolutionCheck, ProcedureArgumentCoercion, 
ResolveMergeIntoTableReferences, ResolveProcedures, 
RewriteDeleteFromIcebergTable, RewriteMergeIntoTable, RewriteUpdateTable}
 import org.apache.spark.sql.catalyst.optimizer._
+import 
org.apache.spark.sql.catalyst.parser.extensions.IcebergSparkSqlExtensionsParser
 import 
org.apache.spark.sql.execution.datasources.v2.{ExtendedDataSourceV2Strategy, 
ExtendedV2Writes, OptimizeMetadataOnlyDeleteFromIcebergTable, 
ReplaceRewrittenRowLevelCommand, RowLevelCommandScanRelationPushDown}
 import 
org.apache.spark.sql.execution.dynamicpruning.RowLevelCommandDynamicPruning
 
@@ -79,6 +80,12 @@ class ArcticSparkExtensions extends (SparkSessionExtensions 
=> Unit) {
 
     // arctic strategy rules
     extensions.injectPlannerStrategy { spark => 
execution.ExtendedArcticStrategy(spark) }
+
+    // iceberg sql parser extensions
+    extensions.injectParser { case (_, parser) => new 
IcebergSparkSqlExtensionsParser(parser) }
+
+    // iceberg procedure analyzer extensions
+    extensions.injectResolutionRule { spark => ResolveProcedures(spark) }
   }
 
 }

Reply via email to