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

mbod 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 f0a98c7  HIVE-25989: HBase CTLT failure rollback should not drop the 
underlying HBase table (#3076) (Marton Bod, reviewed by Peter Vary)
f0a98c7 is described below

commit f0a98c7f03153982adee4b8f5fb698b4775ab924
Author: Marton Bod <[email protected]>
AuthorDate: Thu Mar 10 12:09:54 2022 +0100

    HIVE-25989: HBase CTLT failure rollback should not drop the underlying 
HBase table (#3076) (Marton Bod, reviewed by Peter Vary)
---
 hbase-handler/pom.xml                              |   6 +
 .../apache/hadoop/hive/hbase/HBaseMetaHook.java    |  12 +-
 .../apache/hadoop/hive/hbase/TestHBaseQueries.java | 132 +++++++++++++++++++++
 .../ddl/table/create/like/CreateTableLikeDesc.java |   2 +
 .../hadoop/hive/ql/parse/SemanticAnalyzer.java     |   1 +
 .../thrift/gen-cpp/hive_metastore_constants.cpp    |   2 +
 .../gen/thrift/gen-cpp/hive_metastore_constants.h  |   1 +
 .../metastore/api/hive_metastoreConstants.java     |   2 +
 .../src/gen/thrift/gen-php/metastore/Constant.php  |   6 +
 .../gen/thrift/gen-py/hive_metastore/constants.py  |   1 +
 .../gen/thrift/gen-rb/hive_metastore_constants.rb  |   2 +
 .../src/main/thrift/hive_metastore.thrift          |   1 +
 .../apache/hadoop/hive/metastore/HMSHandler.java   |   2 +
 13 files changed, 169 insertions(+), 1 deletion(-)

diff --git a/hbase-handler/pom.xml b/hbase-handler/pom.xml
index d01b3b9..bd14c62 100644
--- a/hbase-handler/pom.xml
+++ b/hbase-handler/pom.xml
@@ -246,6 +246,12 @@
       <groupId>org.apache.avro</groupId>
       <artifactId>avro</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.hive</groupId>
+      <artifactId>hive-standalone-metastore-server</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+    </dependency>
   </dependencies>
   <build>
     <sourceDirectory>${basedir}/src/java</sourceDirectory>
diff --git 
a/hbase-handler/src/java/org/apache/hadoop/hive/hbase/HBaseMetaHook.java 
b/hbase-handler/src/java/org/apache/hadoop/hive/hbase/HBaseMetaHook.java
index f01ed57..4e9f507 100644
--- a/hbase-handler/src/java/org/apache/hadoop/hive/hbase/HBaseMetaHook.java
+++ b/hbase-handler/src/java/org/apache/hadoop/hive/hbase/HBaseMetaHook.java
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.hive.hbase;
 
+import java.util.Optional;
 import org.apache.commons.io.IOUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HColumnDescriptor;
@@ -41,6 +42,8 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
+import static 
org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.TABLE_IS_CTLT;
+
 /**
  * MetaHook for HBase. Updates the table data in HBase too. Not thread safe, 
and cleanup should
  * be used after usage.
@@ -49,6 +52,7 @@ public class HBaseMetaHook implements HiveMetaHook, Closeable 
{
   private static final Logger LOG = 
LoggerFactory.getLogger(HBaseMetaHook.class);
   private Configuration hbaseConf;
   private Admin admin;
+  private boolean isCTLT;
 
   public HBaseMetaHook(Configuration hbaseConf) {
     this.hbaseConf = hbaseConf;
@@ -124,6 +128,12 @@ public class HBaseMetaHook implements HiveMetaHook, 
Closeable {
     if (tbl.getSd().getLocation() != null) {
       throw new MetaException("LOCATION may not be specified for HBase.");
     }
+    // we shouldn't delete the hbase table in case of CREATE TABLE ... LIKE 
(CTLT) failures since we'd remove the
+    // hbase table for the original table too. Let's save the value of CTLT 
here, because this param will be gone
+    isCTLT = Optional.ofNullable(tbl.getParameters())
+        .map(params -> params.get(TABLE_IS_CTLT))
+        .map(Boolean::parseBoolean)
+        .orElse(false);
 
     org.apache.hadoop.hbase.client.Table htable = null;
 
@@ -187,7 +197,7 @@ public class HBaseMetaHook implements HiveMetaHook, 
Closeable {
     String tableName = getHBaseTableName(table);
     boolean isPurge = !MetaStoreUtils.isExternalTable(table) || 
MetaStoreUtils.isExternalTablePurge(table);
     try {
-      if (isPurge && 
getHBaseAdmin().tableExists(TableName.valueOf(tableName))) {
+      if (isPurge && getHBaseAdmin().tableExists(TableName.valueOf(tableName)) 
&& !isCTLT) {
         // we have created an HBase table, so we delete it to roll back;
         if (getHBaseAdmin().isTableEnabled(TableName.valueOf(tableName))) {
           getHBaseAdmin().disableTable(TableName.valueOf(tableName));
diff --git 
a/hbase-handler/src/test/org/apache/hadoop/hive/hbase/TestHBaseQueries.java 
b/hbase-handler/src/test/org/apache/hadoop/hive/hbase/TestHBaseQueries.java
new file mode 100644
index 0000000..da69f08
--- /dev/null
+++ b/hbase-handler/src/test/org/apache/hadoop/hive/hbase/TestHBaseQueries.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hive.hbase;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.MiniHBaseCluster;
+import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.ql.DriverFactory;
+import org.apache.hadoop.hive.ql.IDriver;
+import org.apache.hadoop.hive.ql.processors.CommandProcessorException;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory;
+import org.apache.hadoop.hive.ql.session.SessionState;
+import org.apache.hadoop.hive.metastore.utils.TestTxnDbUtil;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestHBaseQueries {
+
+  private static MiniZooKeeperCluster zooKeeperCluster;
+  private static MiniHBaseCluster miniHBaseCluster;
+  private final HiveConf baseConf;
+  private IDriver driver;
+
+  /**
+   * Test class for running queries using HBase tables. Creates a mini ZK and 
an HBase test cluster.
+   * Each test method must instantiate a driver object first, using either the 
baseConf or a modified version of that.
+   * Once finished, each test method must take care of cleaning up any 
database objects they've created (tables,
+   * databases, etc.), otherwise those will be visible for subsequent test 
methods too.
+   */
+  public TestHBaseQueries() throws Exception {
+    baseConf = new HiveConf(HBaseConfiguration.create(), 
TestHBaseQueries.class);
+    baseConf.set(HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER.varname, 
SQLStdHiveAuthorizerFactory.class.getName());
+
+    // set up Zookeeper
+    File tmpDir = Files.createTempDirectory(Paths.get("/tmp/"), 
"tmp_").toFile();
+    System.setProperty("zookeeper.4lw.commands.whitelist", "stat");
+    zooKeeperCluster = new MiniZooKeeperCluster();
+    int zkPort = zooKeeperCluster.startup(tmpDir);
+    baseConf.setInt("hbase.zookeeper.property.clientPort", zkPort);
+
+    // set up HBase
+    baseConf.setBoolean("hbase.netty.nativetransport", false);
+    HBaseTestingUtility util = new HBaseTestingUtility(baseConf);
+    util.setZkCluster(zooKeeperCluster);
+    miniHBaseCluster = util.startMiniHBaseCluster(1, 1);
+
+    // set up HMS backend DB
+    TestTxnDbUtil.setConfValues(baseConf);
+    TestTxnDbUtil.cleanDb(baseConf);
+    TestTxnDbUtil.prepDb(baseConf);
+  }
+
+  @AfterClass
+  public static void tearDown() throws IOException {
+    if (miniHBaseCluster != null) {
+      miniHBaseCluster.shutdown();
+    }
+    if (zooKeeperCluster != null) {
+      zooKeeperCluster.shutdown();
+    }
+  }
+
+  @Before
+  public void before() {
+    SessionState.start(baseConf);
+  }
+
+  @After
+  public void after() throws Exception {
+    if (driver != null) {
+      driver.close();
+    }
+    TestTxnDbUtil.cleanDb(baseConf);
+  }
+
+  @Test
+  public void testRollbackDoesNotDeleteOriginTableWhenCTLTFails() throws 
CommandProcessorException {
+    HiveConf conf = new HiveConf(baseConf);
+    conf.setVar(HiveConf.ConfVars.HIVE_TXN_MANAGER, 
"org.apache.hadoop.hive.ql.lockmgr.DbTxnManager");
+    conf.setBoolVar(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY, true);
+    conf.setBoolVar(HiveConf.ConfVars.HIVE_STRICT_MANAGED_TABLES, true);
+    conf.setBoolVar(HiveConf.ConfVars.CREATE_TABLES_AS_ACID, true);
+    conf.setBoolVar(HiveConf.ConfVars.HIVE_CREATE_TABLES_AS_INSERT_ONLY, true);
+    conf.setVar(HiveConf.ConfVars.HIVEDEFAULTMANAGEDFILEFORMAT, "ORC");
+
+    driver = DriverFactory.newDriver(conf);
+
+    driver.run("CREATE EXTERNAL TABLE `old_hbase_hive_table`(\n" +
+        "   `key` int COMMENT '',\n" +
+        "   `value` string COMMENT '')\n" +
+        " ROW FORMAT SERDE\n" +
+        "   'org.apache.hadoop.hive.hbase.HBaseSerDe'\n" +
+        " STORED BY\n" +
+        "   'org.apache.hadoop.hive.hbase.HBaseStorageHandler'\n" +
+        " WITH SERDEPROPERTIES (\n" +
+        "   'hbase.columns.mapping'=':key,cf:cf')\n" +
+        " TBLPROPERTIES ('hbase.table.name'='hbase_hive_table')");
+    try {
+      driver.run("create table new_hbase_hive_table like 
old_hbase_hive_table");
+    } catch (Exception e) {
+      // expected - above command will try to create a transactional table but 
will fail
+    }
+    // original table is still present, rollback() has not deleted it
+    driver.run("select * from old_hbase_hive_table");
+
+    driver.run("drop table old_hbase_hive_table");
+  }
+}
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/like/CreateTableLikeDesc.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/like/CreateTableLikeDesc.java
index 3e850f0..ba99d3b 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/like/CreateTableLikeDesc.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/like/CreateTableLikeDesc.java
@@ -19,6 +19,7 @@
 package org.apache.hadoop.hive.ql.ddl.table.create.like;
 
 import static 
org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.TABLE_IS_CTAS;
+import static 
org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.TABLE_IS_CTLT;
 
 import java.io.Serializable;
 import java.util.HashMap;
@@ -118,6 +119,7 @@ public class CreateTableLikeDesc implements DDLDesc, 
Serializable {
   public Map<String, String> getTblPropsExplain() {
     HashMap<String, String> copy = new HashMap<>(tblProps);
     copy.remove(TABLE_IS_CTAS);
+    copy.remove(TABLE_IS_CTLT);
     return copy;
   }
 
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
index d179a94..f0d5747 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
@@ -13678,6 +13678,7 @@ public class SemanticAnalyzer extends 
BaseSemanticAnalyzer {
       tblProps = validateAndAddDefaultProperties(
           tblProps, isExt, storageFormat, dbDotTab, sortCols, 
isMaterialization, isTemporary,
           isTransactional, isManaged);
+      tblProps.put(hive_metastoreConstants.TABLE_IS_CTLT, "true");
       addDbAndTabToOutputs(new String[] {qualifiedTabName.getDb(), 
qualifiedTabName.getTable()},
           TableType.MANAGED_TABLE, isTemporary, tblProps, storageFormat);
 
diff --git 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.cpp
 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.cpp
index 1b981f5..097ed89 100644
--- 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.cpp
+++ 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.cpp
@@ -75,6 +75,8 @@ hive_metastoreConstants::hive_metastoreConstants() {
 
   TABLE_IS_CTAS = "created_with_ctas";
 
+  TABLE_IS_CTLT = "created_with_ctlt";
+
   PARTITION_TRANSFORM_SPEC = "partition_transform_spec";
 
   NO_CLEANUP = "no_cleanup";
diff --git 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.h
 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.h
index d5f7cdf..807e777 100644
--- 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.h
+++ 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-cpp/hive_metastore_constants.h
@@ -47,6 +47,7 @@ class hive_metastoreConstants {
   std::string DRUID_CONFIG_PREFIX;
   std::string JDBC_CONFIG_PREFIX;
   std::string TABLE_IS_CTAS;
+  std::string TABLE_IS_CTLT;
   std::string PARTITION_TRANSFORM_SPEC;
   std::string NO_CLEANUP;
   std::string CTAS_LEGACY_CONFIG;
diff --git 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-javabean/org/apache/hadoop/hive/metastore/api/hive_metastoreConstants.java
 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-javabean/org/apache/hadoop/hive/metastore/api/hive_metastoreConstants.java
index 2851b22..8576117 100644
--- 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-javabean/org/apache/hadoop/hive/metastore/api/hive_metastoreConstants.java
+++ 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-javabean/org/apache/hadoop/hive/metastore/api/hive_metastoreConstants.java
@@ -73,6 +73,8 @@ package org.apache.hadoop.hive.metastore.api;
 
   public static final java.lang.String TABLE_IS_CTAS = "created_with_ctas";
 
+  public static final java.lang.String TABLE_IS_CTLT = "created_with_ctlt";
+
   public static final java.lang.String PARTITION_TRANSFORM_SPEC = 
"partition_transform_spec";
 
   public static final java.lang.String NO_CLEANUP = "no_cleanup";
diff --git 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-php/metastore/Constant.php
 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-php/metastore/Constant.php
index b6f4e80..9210480 100644
--- 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-php/metastore/Constant.php
+++ 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-php/metastore/Constant.php
@@ -50,6 +50,7 @@ final class Constant extends \Thrift\Type\TConstant
     static protected $DRUID_CONFIG_PREFIX;
     static protected $JDBC_CONFIG_PREFIX;
     static protected $TABLE_IS_CTAS;
+    static protected $TABLE_IS_CTLT;
     static protected $PARTITION_TRANSFORM_SPEC;
     static protected $NO_CLEANUP;
     static protected $CTAS_LEGACY_CONFIG;
@@ -214,6 +215,11 @@ final class Constant extends \Thrift\Type\TConstant
         return "created_with_ctas";
     }
 
+    protected static function init_TABLE_IS_CTLT()
+    {
+        return "created_with_ctlt";
+    }
+
     protected static function init_PARTITION_TRANSFORM_SPEC()
     {
         return "partition_transform_spec";
diff --git 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-py/hive_metastore/constants.py
 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-py/hive_metastore/constants.py
index ef5a2b1..f582bdc 100644
--- 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-py/hive_metastore/constants.py
+++ 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-py/hive_metastore/constants.py
@@ -44,6 +44,7 @@ TABLE_BUCKETING_VERSION = "bucketing_version"
 DRUID_CONFIG_PREFIX = "druid."
 JDBC_CONFIG_PREFIX = "hive.sql."
 TABLE_IS_CTAS = "created_with_ctas"
+TABLE_IS_CTLT = "created_with_ctlt"
 PARTITION_TRANSFORM_SPEC = "partition_transform_spec"
 NO_CLEANUP = "no_cleanup"
 CTAS_LEGACY_CONFIG = "create_table_as_external"
diff --git 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-rb/hive_metastore_constants.rb
 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-rb/hive_metastore_constants.rb
index d441f3a..b9b4ce8 100644
--- 
a/standalone-metastore/metastore-common/src/gen/thrift/gen-rb/hive_metastore_constants.rb
+++ 
b/standalone-metastore/metastore-common/src/gen/thrift/gen-rb/hive_metastore_constants.rb
@@ -71,6 +71,8 @@ JDBC_CONFIG_PREFIX = %q"hive.sql."
 
 TABLE_IS_CTAS = %q"created_with_ctas"
 
+TABLE_IS_CTLT = %q"created_with_ctlt"
+
 PARTITION_TRANSFORM_SPEC = %q"partition_transform_spec"
 
 NO_CLEANUP = %q"no_cleanup"
diff --git 
a/standalone-metastore/metastore-common/src/main/thrift/hive_metastore.thrift 
b/standalone-metastore/metastore-common/src/main/thrift/hive_metastore.thrift
index a03e3c9..f5dfa54 100644
--- 
a/standalone-metastore/metastore-common/src/main/thrift/hive_metastore.thrift
+++ 
b/standalone-metastore/metastore-common/src/main/thrift/hive_metastore.thrift
@@ -3136,6 +3136,7 @@ const string TABLE_BUCKETING_VERSION = 
"bucketing_version",
 const string DRUID_CONFIG_PREFIX = "druid.",
 const string JDBC_CONFIG_PREFIX = "hive.sql.",
 const string TABLE_IS_CTAS = "created_with_ctas",
+const string TABLE_IS_CTLT = "created_with_ctlt",
 const string PARTITION_TRANSFORM_SPEC = "partition_transform_spec",
 const string NO_CLEANUP = "no_cleanup",
 const string CTAS_LEGACY_CONFIG = "create_table_as_external",
\ No newline at end of file
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
index 83a838f..6e8b85d 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
@@ -121,6 +121,7 @@ import static 
org.apache.hadoop.hive.metastore.Warehouse.DEFAULT_CATALOG_NAME;
 import static 
org.apache.hadoop.hive.metastore.Warehouse.DEFAULT_DATABASE_COMMENT;
 import static org.apache.hadoop.hive.metastore.Warehouse.DEFAULT_DATABASE_NAME;
 import static 
org.apache.hadoop.hive.metastore.Warehouse.getCatalogQualifiedTableName;
+import static 
org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.TABLE_IS_CTLT;
 import static org.apache.hadoop.hive.metastore.utils.MetaStoreUtils.CAT_NAME;
 import static org.apache.hadoop.hive.metastore.utils.MetaStoreUtils.DB_NAME;
 import static 
org.apache.hadoop.hive.metastore.utils.MetaStoreUtils.getDefaultCatalog;
@@ -2283,6 +2284,7 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
 
     if (tbl.getParameters() != null) {
       tbl.getParameters().remove(TABLE_IS_CTAS);
+      tbl.getParameters().remove(TABLE_IS_CTLT);
     }
 
     // If the given table has column statistics, save it here. We will update 
it later.

Reply via email to