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 {