You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by dk...@apache.org on 2022/03/24 15:39:13 UTC

[hive] branch master updated: HIVE-26052: Non blocking DROP MATERIALIZED VIEW implementation (Denys Kuzmenko, reviewed by Krisztian Kasa)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new d4d5d88  HIVE-26052: Non blocking DROP MATERIALIZED VIEW implementation (Denys Kuzmenko, reviewed by Krisztian Kasa)
d4d5d88 is described below

commit d4d5d888ee2207215920eb83820b872f47cfa327
Author: Denys Kuzmenko <dk...@cloudera.com>
AuthorDate: Thu Mar 24 16:38:57 2022 +0100

    HIVE-26052: Non blocking DROP MATERIALIZED VIEW implementation (Denys Kuzmenko, reviewed by Krisztian Kasa)
    
    Closes #3111
---
 .../hive/ql/ddl/table/drop/DropTableAnalyzer.java  |   6 +-
 .../AlterMaterializedViewRewriteAnalyzer.java      |   2 +-
 .../drop/DropMaterializedViewAnalyzer.java         |   9 +-
 .../drop/DropMaterializedViewOperation.java        |   2 +-
 .../apache/hadoop/hive/ql/hooks/WriteEntity.java   |   3 +-
 .../org/apache/hadoop/hive/ql/io/AcidUtils.java    |  12 ++-
 .../apache/hadoop/hive/ql/parse/TaskCompiler.java  |  23 +++--
 .../org/apache/hadoop/hive/ql/TestTxnCommands.java |  93 +++++++++++++++++++
 .../hadoop/hive/ql/lockmgr/TestDbTxnManager2.java  | 103 +++++++++++++++++++++
 .../apache/hadoop/hive/metastore/Warehouse.java    |   2 +-
 10 files changed, 236 insertions(+), 19 deletions(-)

diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableAnalyzer.java
index 1507ca7..1a3a77f 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableAnalyzer.java
@@ -56,11 +56,7 @@ public class DropTableAnalyzer extends BaseSemanticAnalyzer {
     if (table != null) {
       inputs.add(new ReadEntity(table));
 
-      boolean tableWithSuffix = (HiveConf.getBoolVar(conf, ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX)
-          || HiveConf.getBoolVar(conf, ConfVars.HIVE_ACID_LOCKLESS_READS_ENABLED))
-        && AcidUtils.isTransactionalTable(table)
-        && Boolean.parseBoolean(table.getProperty(SOFT_DELETE_TABLE));
-
+      boolean tableWithSuffix = AcidUtils.isTableSoftDeleteEnabled(table, conf);
       outputs.add(new WriteEntity(table, 
         tableWithSuffix ? WriteType.DDL_EXCL_WRITE : WriteType.DDL_EXCLUSIVE));
     }
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/alter/rewrite/AlterMaterializedViewRewriteAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/alter/rewrite/AlterMaterializedViewRewriteAnalyzer.java
index 0dd0c4f..a8431a4 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/alter/rewrite/AlterMaterializedViewRewriteAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/alter/rewrite/AlterMaterializedViewRewriteAnalyzer.java
@@ -85,7 +85,7 @@ public class AlterMaterializedViewRewriteAnalyzer extends BaseSemanticAnalyzer {
     }
 
     inputs.add(new ReadEntity(materializedViewTable));
-    outputs.add(new WriteEntity(materializedViewTable, AcidUtils.isLocklessReadsSupported(materializedViewTable, conf) ?
+    outputs.add(new WriteEntity(materializedViewTable, AcidUtils.isLocklessReadsEnabled(materializedViewTable, conf) ?
       WriteEntity.WriteType.DDL_EXCL_WRITE : WriteEntity.WriteType.DDL_EXCLUSIVE));
 
     // Create task for alterMVRewriteDesc
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewAnalyzer.java
index 828d85d..433fab5 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewAnalyzer.java
@@ -26,12 +26,16 @@ import org.apache.hadoop.hive.ql.ddl.DDLSemanticAnalyzerFactory.DDLType;
 import org.apache.hadoop.hive.ql.exec.TaskFactory;
 import org.apache.hadoop.hive.ql.hooks.ReadEntity;
 import org.apache.hadoop.hive.ql.hooks.WriteEntity;
+import org.apache.hadoop.hive.ql.hooks.WriteEntity.WriteType;
+import org.apache.hadoop.hive.ql.io.AcidUtils;
 import org.apache.hadoop.hive.ql.metadata.Table;
 import org.apache.hadoop.hive.ql.parse.ASTNode;
 import org.apache.hadoop.hive.ql.parse.BaseSemanticAnalyzer;
 import org.apache.hadoop.hive.ql.parse.HiveParser;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
 
+import static org.apache.hadoop.hive.common.AcidConstants.SOFT_DELETE_TABLE;
+
 /**
  * Analyzer for drop materialized view commands.
  */
@@ -50,7 +54,10 @@ public class DropMaterializedViewAnalyzer extends BaseSemanticAnalyzer {
     Table materializedView = getTable(viewName, throwException);
     if (materializedView != null) {
       inputs.add(new ReadEntity(materializedView));
-      outputs.add(new WriteEntity(materializedView, WriteEntity.WriteType.DDL_EXCLUSIVE));
+
+      boolean tableWithSuffix = AcidUtils.isTableSoftDeleteEnabled(materializedView, conf);
+      outputs.add(new WriteEntity(materializedView,
+        tableWithSuffix ? WriteType.DDL_EXCL_WRITE : WriteType.DDL_EXCLUSIVE));
     }
 
     DropMaterializedViewDesc desc = new DropMaterializedViewDesc(viewName, ifExists);
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewOperation.java b/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewOperation.java
index cda84eb..9f18b2f 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewOperation.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/ddl/view/materialized/drop/DropMaterializedViewOperation.java
@@ -53,7 +53,7 @@ public class DropMaterializedViewOperation extends DDLOperation<DropMaterialized
     }
 
     // TODO: API w/catalog name
-    context.getDb().dropTable(desc.getTableName(), false);
+    context.getDb().dropTable(table, false);
     HiveMaterializedViewsRegistry.get().dropMaterializedView(table.getDbName(), table.getTableName());
     DDLUtils.addIfAbsentByName(new WriteEntity(table, WriteEntity.WriteType.DDL_NO_LOCK), context);
 
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/hooks/WriteEntity.java b/ql/src/java/org/apache/hadoop/hive/ql/hooks/WriteEntity.java
index 0ea01fc..8b5cf47 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/hooks/WriteEntity.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/hooks/WriteEntity.java
@@ -18,7 +18,6 @@
 
 package org.apache.hadoop.hive.ql.hooks;
 
-import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.metastore.api.DataConnector;
@@ -233,7 +232,7 @@ public class WriteEntity extends Entity implements Serializable {
       return WriteType.DDL_EXCLUSIVE;
 
     case RENAME:
-      return AcidUtils.isLocklessReadsSupported(table, conf) ? 
+      return AcidUtils.isLocklessReadsEnabled(table, conf) ? 
           WriteType.DDL_EXCL_WRITE : WriteType.DDL_EXCLUSIVE;
 
     case ADDPARTITION:
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java b/ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java
index 4d755cb..c5ed434 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.hive.ql.io;
 
+import static org.apache.hadoop.hive.common.AcidConstants.SOFT_DELETE_TABLE;
 import static org.apache.hadoop.hive.ql.exec.Utilities.COPY_KEYWORD;
 import static org.apache.hadoop.hive.ql.parse.CalcitePlanner.ASTSearcher;
 
@@ -409,11 +410,18 @@ public class AcidUtils {
         + String.format(DELTA_DIGITS, visibilityTxnId);
   }
 
-  public static boolean isLocklessReadsSupported(Table table, HiveConf conf) {
+  public static boolean isLocklessReadsEnabled(Table table, HiveConf conf) {
     return HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ACID_LOCKLESS_READS_ENABLED)
         && AcidUtils.isTransactionalTable(table);
   }
 
+  public static boolean isTableSoftDeleteEnabled(Table table, HiveConf conf) {
+    return (HiveConf.getBoolVar(conf, ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX)
+        || HiveConf.getBoolVar(conf, ConfVars.HIVE_ACID_LOCKLESS_READS_ENABLED))
+      && AcidUtils.isTransactionalTable(table)
+      && Boolean.parseBoolean(table.getProperty(SOFT_DELETE_TABLE));
+  }
+
   /**
    * Represents bucketId and copy_N suffix
    */
@@ -3121,7 +3129,7 @@ public class AcidUtils {
       return TxnType.COMPACTION;
     }
     // check if soft delete
-    if (tree.getToken().getType() == HiveParser.TOK_DROPTABLE 
+    if ((tree.getToken().getType() == HiveParser.TOK_DROPTABLE || tree.getToken().getType() == HiveParser.TOK_DROP_MATERIALIZED_VIEW)
       && (HiveConf.getBoolVar(conf, ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX)
         || HiveConf.getBoolVar(conf, ConfVars.HIVE_ACID_LOCKLESS_READS_ENABLED))){
       return TxnType.SOFT_DELETE;
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/TaskCompiler.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/TaskCompiler.java
index 21bbb95..1d5a5df 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/TaskCompiler.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/TaskCompiler.java
@@ -31,7 +31,6 @@ import org.apache.hadoop.hive.conf.HiveConf.ResultFileFormat;
 import org.apache.hadoop.hive.metastore.Warehouse;
 import org.apache.hadoop.hive.metastore.api.hive_metastoreConstants;
 import org.apache.hadoop.hive.metastore.api.MetaException;
-import org.apache.hadoop.hive.metastore.TableType;
 import org.apache.hadoop.hive.ql.Context;
 import org.apache.hadoop.hive.ql.ErrorMsg;
 import org.apache.hadoop.hive.ql.QueryState;
@@ -99,8 +98,12 @@ import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
+import static org.apache.hadoop.hive.common.AcidConstants.SOFT_DELETE_PATH_SUFFIX;
+import static org.apache.hadoop.hive.ql.io.AcidUtils.DELTA_DIGITS;
+
 /**
  * TaskCompiler is a the base class for classes that compile
  * operator pipelines into tasks.
@@ -512,23 +515,31 @@ public abstract class TaskCompiler {
 
   private Path getDefaultCtasLocation(final ParseContext pCtx) throws SemanticException {
     try {
-      String protoName = null;
+      String protoName = null, suffix = "";
       boolean isExternal = false;
+      
       if (pCtx.getQueryProperties().isCTAS()) {
         protoName = pCtx.getCreateTable().getDbTableName();
         isExternal = pCtx.getCreateTable().isExternal();
+      
       } else if (pCtx.getQueryProperties().isMaterializedView()) {
         protoName = pCtx.getCreateViewDesc().getViewName();
+        boolean createMVUseSuffix = HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX)
+          || HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ACID_LOCKLESS_READS_ENABLED);
+
+        if (createMVUseSuffix) {
+          long txnId = Optional.ofNullable(pCtx.getContext())
+            .map(ctx -> ctx.getHiveTxnManager().getCurrentTxnId()).orElse(0L);
+          suffix = SOFT_DELETE_PATH_SUFFIX + String.format(DELTA_DIGITS, txnId);
+        }
       }
       String[] names = Utilities.getDbTableName(protoName);
       if (!db.databaseExists(names[0])) {
         throw new SemanticException("ERROR: The database " + names[0] + " does not exist.");
       }
       Warehouse wh = new Warehouse(conf);
-      return wh.getDefaultTablePath(db.getDatabase(names[0]), names[1], isExternal);
-    } catch (HiveException e) {
-      throw new SemanticException(e);
-    } catch (MetaException e) {
+      return wh.getDefaultTablePath(db.getDatabase(names[0]), names[1] + suffix, isExternal);
+    } catch (HiveException | MetaException e) {
       throw new SemanticException(e);
     }
   }
diff --git a/ql/src/test/org/apache/hadoop/hive/ql/TestTxnCommands.java b/ql/src/test/org/apache/hadoop/hive/ql/TestTxnCommands.java
index 1279f15..1092103 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/TestTxnCommands.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/TestTxnCommands.java
@@ -1768,4 +1768,97 @@ public class TestTxnCommands extends TxnCommandsBaseForTests {
       Assert.assertEquals("Unexpected number of compactions in history", 0, resp.getCompactsSize());
     }
   }
+
+  @Test
+  public void testDropMaterializedViewWithSuffix() throws Exception {
+    String tableName = "tab_acid";
+    String mviewName = "mv_" + tableName;
+    runStatementOnDriver("drop materialized view if exists " + mviewName);
+    runStatementOnDriver("drop table if exists " + tableName);
+    HiveConf.setBoolVar(hiveConf, HiveConf.ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX, true);
+
+    runStatementOnDriver("create table " + tableName + "(a int, b int) stored as orc TBLPROPERTIES ('transactional'='true')");
+    runStatementOnDriver("insert into " + tableName + " values(1,2),(3,4)");
+    runStatementOnDriver("create materialized view " + mviewName + " stored as orc TBLPROPERTIES ('transactional'='true') " +
+      "as select a from tab_acid where b > 1");
+    runStatementOnDriver("drop materialized view " + mviewName);
+
+    int count = TestTxnDbUtil.countQueryAgent(hiveConf,
+      "select count(*) from TXN_TO_WRITE_ID where T2W_TABLE = '" + mviewName + "'");
+    Assert.assertEquals(1, count);
+
+    FileSystem fs = FileSystem.get(hiveConf);
+    FileStatus[] stat = fs.listStatus(new Path(getWarehouseDir()),
+      t -> t.getName().matches(mviewName + SOFT_DELETE_TABLE_PATTERN));
+    if (1 != stat.length) {
+      Assert.fail("Materialized view data was removed from FS");
+    }
+    MetastoreTaskThread houseKeeperService = new AcidHouseKeeperService();
+    houseKeeperService.setConf(hiveConf);
+
+    houseKeeperService.run();
+    count = TestTxnDbUtil.countQueryAgent(hiveConf,
+      "select count(*) from TXN_TO_WRITE_ID where T2W_TABLE = '" + mviewName + "'");
+    Assert.assertEquals(0, count);
+
+    try {
+      runStatementOnDriver("select * from " + mviewName);
+    } catch (Exception ex) {
+      Assert.assertTrue(ex.getMessage().contains(
+        ErrorMsg.INVALID_TABLE.getMsg(StringUtils.wrap(mviewName, "'"))));
+    }
+    // Check status of compaction job
+    TxnStore txnHandler = TxnUtils.getTxnStore(hiveConf);
+    ShowCompactResponse resp = txnHandler.showCompact(new ShowCompactRequest());
+
+    Assert.assertEquals("Unexpected number of compactions in history", 1, resp.getCompactsSize());
+    Assert.assertEquals("Unexpected 0 compaction state",
+      TxnStore.CLEANING_RESPONSE, resp.getCompacts().get(0).getState());
+
+    runCleaner(hiveConf);
+
+    FileStatus[] status = fs.listStatus(new Path(getWarehouseDir()),
+      t -> t.getName().matches(mviewName + SOFT_DELETE_TABLE_PATTERN));
+    Assert.assertEquals(0, status.length);
+  }
+
+  @Test
+  public void testDropMaterializedViewWithoutSuffix() throws Exception {
+    String tableName = "tab_acid";
+    String mviewName = "mv_" + tableName;
+    runStatementOnDriver("drop materialized view if exists " + mviewName);
+
+    for (boolean enabled : Arrays.asList(false, true)) {
+      runStatementOnDriver("drop table if exists " + tableName);
+      HiveConf.setBoolVar(hiveConf, HiveConf.ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX, enabled);
+      
+      runStatementOnDriver("create table " + tableName + "(a int, b int) stored as orc TBLPROPERTIES ('transactional'='true')");
+      runStatementOnDriver("insert into " + tableName + " values(1,2),(3,4)");
+      runStatementOnDriver("create materialized view " + mviewName + " stored as orc TBLPROPERTIES ('transactional'='true') " +
+        "as select a from tab_acid where b > 1");
+
+      HiveConf.setBoolVar(hiveConf, HiveConf.ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX, !enabled);
+      runStatementOnDriver("drop materialized view " + mviewName);
+
+      int count = TestTxnDbUtil.countQueryAgent(hiveConf,
+        "select count(*) from TXN_TO_WRITE_ID where T2W_TABLE = '" + mviewName + "'");
+      Assert.assertEquals(0, count);
+
+      FileSystem fs = FileSystem.get(hiveConf);
+      FileStatus[] stat = fs.listStatus(new Path(getWarehouseDir()),
+        t -> t.getName().equals(mviewName));
+      Assert.assertEquals(0, stat.length);
+
+      try {
+        runStatementOnDriver("select * from " + mviewName);
+      } catch (Exception ex) {
+        Assert.assertTrue(ex.getMessage().contains(
+          ErrorMsg.INVALID_TABLE.getMsg(StringUtils.wrap(mviewName, "'"))));
+      }
+      // Check status of compaction job
+      TxnStore txnHandler = TxnUtils.getTxnStore(hiveConf);
+      ShowCompactResponse resp = txnHandler.showCompact(new ShowCompactRequest());
+      Assert.assertEquals("Unexpected number of compactions in history", 0, resp.getCompactsSize());
+    }
+  }
 }
diff --git a/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java b/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java
index 8e4d6d9..e6dd859 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java
@@ -3713,4 +3713,107 @@ public class TestDbTxnManager2 extends DbTxnManagerEndToEndTestBase{
     List<ShowLocksResponseElement> locks = getLocks();
     Assert.assertEquals("Unexpected lock count", 0, locks.size());
   }
+
+  @Test
+  public void testDropMaterializedViewNonBlocking() throws Exception {
+    testDropMaterializedView(false);
+  }
+  @Test
+  public void testDropMaterializedViewBlocking() throws Exception {
+    testDropMaterializedView(true);
+  }
+
+  private void testDropMaterializedView(boolean blocking) throws Exception {
+    driver.run("drop materialized view if exists mv_tab_acid");
+    dropTable(new String[] {"tab_acid"});
+    FileSystem fs = FileSystem.get(conf);
+
+    HiveConf.setBoolVar(conf, HiveConf.ConfVars.HIVE_ACID_LOCKLESS_READS_ENABLED, !blocking);
+    HiveConf.setIntVar(conf, HiveConf.ConfVars.HIVE_LOCKS_PARTITION_THRESHOLD, 1);
+    driver = Mockito.spy(driver);
+
+    HiveConf.setBoolVar(driver2.getConf(), HiveConf.ConfVars.HIVE_ACID_CREATE_TABLE_USE_SUFFIX, !blocking);
+    driver2 = Mockito.spy(driver2);
+
+    driver.run("create table if not exists tab_acid (a int, b int) partitioned by (p string) " +
+      "stored as orc TBLPROPERTIES ('transactional'='true')");
+    driver.run("insert into tab_acid partition(p) (a,b,p) values(1,2,'foo'),(3,4,'bar')");
+
+    driver.run("create materialized view mv_tab_acid partitioned on (p) " +
+      "stored as orc TBLPROPERTIES ('transactional'='true') as select a, p from tab_acid where b > 1");
+
+    driver.compileAndRespond("select a, p from tab_acid where b > 1");
+    List<String> res = new ArrayList<>();
+
+    driver.lockAndRespond();
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 2, locks.size());
+
+    checkLock(LockType.SHARED_READ,
+      LockState.ACQUIRED, "default", "tab_acid", null, locks);
+    checkLock(LockType.SHARED_READ,
+      LockState.ACQUIRED, "default", "mv_tab_acid", null, locks);
+
+    DbTxnManager txnMgr2 = (DbTxnManager) TxnManagerFactory.getTxnManagerFactory().getTxnManager(conf);
+    swapTxnManager(txnMgr2);
+    driver2.compileAndRespond("drop materialized view if exists mv_tab_acid");
+
+    if (blocking) {
+      txnMgr2.acquireLocks(driver2.getPlan(), ctx, null, false);
+      locks = getLocks();
+
+      ShowLocksResponseElement checkLock = checkLock(LockType.EXCLUSIVE,
+        LockState.WAITING, "default", "mv_tab_acid", null, locks);
+
+      swapTxnManager(txnMgr);
+      Mockito.doNothing().when(driver).lockAndRespond();
+      driver.run();
+
+      driver.getFetchTask().fetch(res);
+      swapTxnManager(txnMgr2);
+
+      FieldSetter.setField(txnMgr2, txnMgr2.getClass().getDeclaredField("numStatements"), 0);
+      txnMgr2.getMS().unlock(checkLock.getLockid());
+    }
+    driver2.lockAndRespond();
+    locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", blocking ? 1 : 3, locks.size());
+
+    checkLock(blocking ? LockType.EXCLUSIVE : LockType.EXCL_WRITE,
+      LockState.ACQUIRED, "default", "mv_tab_acid", null, locks);
+
+    Mockito.doNothing().when(driver2).lockAndRespond();
+    driver2.run();
+
+    if (!blocking) {
+      swapTxnManager(txnMgr);
+      Mockito.doNothing().when(driver).lockAndRespond();
+      driver.run();
+    }
+    Mockito.reset(driver, driver2);
+
+    FileStatus[] stat = fs.listStatus(new Path(getWarehouseDir()),
+      t -> t.getName().matches("mv_tab_acid" + (blocking ? "" : SOFT_DELETE_TABLE_PATTERN)));
+    if ((blocking ? 0 : 1) != stat.length) {
+      Assert.fail("Table data was " + (blocking ? "not" : "") + "removed from FS");
+    }
+    driver.getFetchTask().fetch(res);
+    Assert.assertEquals("Expecting 2 rows and found " + res.size(), 2, res.size());
+
+    try {
+      driver.run("select * from mv_tab_acid");
+    } catch (CommandProcessorException ex) {
+      Assert.assertEquals(ErrorMsg.INVALID_TABLE.getErrorCode(), ex.getResponseCode());
+    }
+
+    //re-create MV with the same name
+    driver.run("create materialized view mv_tab_acid partitioned on (p) " +
+      "stored as orc TBLPROPERTIES ('transactional'='true') as select a, p from tab_acid where b > 1");
+
+    driver.run("select * from mv_tab_acid ");
+    res = new ArrayList<>();
+    driver.getFetchTask().fetch(res);
+    Assert.assertEquals("Expecting 2 rows and found " + res.size(), 2, res.size());
+    driver.run("drop materialized view mv_tab_acid");
+  }
 }
diff --git a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/Warehouse.java b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/Warehouse.java
index 1711ef6..3e1eb1c 100755
--- a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/Warehouse.java
+++ b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/Warehouse.java
@@ -367,7 +367,7 @@ public class Warehouse {
       dbPath = getDatabaseManagedPath(db);
     }
     if (!isExternal && tableName.matches("(.*)" + SOFT_DELETE_TABLE_PATTERN)) {
-      String[] groups = tableName.split(SOFT_DELETE_PATH_SUFFIX);
+      String[] groups = tableName.split("\\" + SOFT_DELETE_PATH_SUFFIX);
       tableName = String.join(SOFT_DELETE_PATH_SUFFIX, 
           MetaStoreUtils.encodeTableName(groups[0].toLowerCase()), groups[1]);
     } else {