Repository: hive
Updated Branches:
  refs/heads/branch-3 0084f9288 -> 2bf4fef22


HIVE-19639 : a transactional Hive table cannot be imported as an external table 
(Sergey Shelukhin, reviewed by Thejas M Nair)


Project: http://git-wip-us.apache.org/repos/asf/hive/repo
Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/2bf4fef2
Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/2bf4fef2
Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/2bf4fef2

Branch: refs/heads/branch-3
Commit: 2bf4fef22babce90ade5670ff5ce49143be37457
Parents: 0084f92
Author: sergey <ser...@apache.org>
Authored: Tue May 22 12:08:50 2018 -0700
Committer: sergey <ser...@apache.org>
Committed: Tue May 22 14:35:46 2018 -0700

----------------------------------------------------------------------
 .../org/apache/hadoop/hive/ql/io/AcidUtils.java |  5 ++
 .../hive/ql/parse/ImportSemanticAnalyzer.java   | 31 +++++----
 ql/src/test/queries/clientpositive/mm_exim.q    |  8 +++
 .../results/clientpositive/llap/mm_exim.q.out   | 70 ++++++++++++++++++++
 4 files changed, 102 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hive/blob/2bf4fef2/ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java
----------------------------------------------------------------------
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 183515a..4b9a8a1 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
@@ -1932,4 +1932,9 @@ public class AcidUtils {
     }
     return writeId;
   }
+
+  public static void setNonTransactional(Map<String, String> tblProps) {
+    tblProps.put(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL, "false");
+    tblProps.remove(hive_metastoreConstants.TABLE_TRANSACTIONAL_PROPERTIES);
+  }
 }

http://git-wip-us.apache.org/repos/asf/hive/blob/2bf4fef2/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java
----------------------------------------------------------------------
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java
index eb6708b..1a3cef9 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java
@@ -255,16 +255,13 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
     }
 
     if (isExternalSet) {
-      if (AcidUtils.isInsertOnlyTable(tblDesc.getTblProps())) {
-        throw new SemanticException("Cannot import an MM table as external");
-      }
       tblDesc.setExternal(isExternalSet);
       // This condition-check could have been avoided, but to honour the old
       // default of not calling if it wasn't set, we retain that behaviour.
       // TODO:cleanup after verification that the outer if isn't really needed 
here
     }
 
-    if (isLocationSet){
+    if (isLocationSet) {
       tblDesc.setLocation(parsedLocation);
       x.getInputs().add(toReadEntity(new Path(parsedLocation), x.getConf()));
     }
@@ -320,11 +317,16 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
     boolean tableExists = false;
 
     if (table != null) {
-      checkTable(table, tblDesc,replicationSpec, x.getConf());
+      checkTable(table, tblDesc, replicationSpec, x.getConf());
       x.getLOG().debug("table " + tblDesc.getTableName() + " exists: metadata 
checked");
       tableExists = true;
     }
 
+    if (!tableExists && isExternalSet) {
+      // If the user is explicitly importing a new external table, clear txn 
flags from the spec.
+      AcidUtils.setNonTransactional(tblDesc.getTblProps());
+    }
+
     Long writeId = 0L; // Initialize with 0 for non-ACID and non-MM tables.
     int stmtId = 0;
     if (!replicationSpec.isInReplicationScope()
@@ -862,7 +864,7 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
       x.getLOG().debug("table " + tblDesc.getTableName() + " does not exist");
 
       Task<?> t = createTableTask(tblDesc, x);
-      table = createNewTableMetadataObject(tblDesc);
+      table = createNewTableMetadataObject(tblDesc, false);
 
       Database parentDb = x.getHive().getDatabase(tblDesc.getDatabaseName());
 
@@ -898,14 +900,19 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
     }
   }
 
-  private static Table createNewTableMetadataObject(ImportTableDesc tblDesc)
+  private static Table createNewTableMetadataObject(ImportTableDesc tblDesc, 
boolean isRepl)
       throws SemanticException {
     Table newTable = new Table(tblDesc.getDatabaseName(), 
tblDesc.getTableName());
     //so that we know the type of table we are creating: acid/MM to match what 
was exported
     newTable.setParameters(tblDesc.getTblProps());
     if(tblDesc.isExternal() && AcidUtils.isTransactionalTable(newTable)) {
-      throw new SemanticException("External tables may not be transactional: " 
+
-          Warehouse.getQualifiedName(tblDesc.getDatabaseName(), 
tblDesc.getTableName()));
+      if (isRepl) {
+        throw new SemanticException("External tables may not be transactional: 
" +
+            Warehouse.getQualifiedName(tblDesc.getDatabaseName(), 
tblDesc.getTableName()));
+      } else {
+        throw new AssertionError("Internal error: transactional properties not 
set properly"
+            + tblDesc.getTblProps());
+      }
     }
     return newTable;
   }
@@ -1000,7 +1007,7 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
       }
 
       Task t = createTableTask(tblDesc, x);
-      table = createNewTableMetadataObject(tblDesc);
+      table = createNewTableMetadataObject(tblDesc, true);
 
       if (!replicationSpec.isMetadataOnly()) {
         if (isPartitioned(tblDesc)) {
@@ -1033,7 +1040,7 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
       // create the dummy table object for adding repl tasks.
       boolean isOldTableValid = true;
       if (table.isPartitioned() != isPartitioned(tblDesc)) {
-        table = createNewTableMetadataObject(tblDesc);
+        table = createNewTableMetadataObject(tblDesc, true);
         isOldTableValid = false;
       }
 
@@ -1051,7 +1058,7 @@ public class ImportSemanticAnalyzer extends 
BaseSemanticAnalyzer {
               ptn = x.getHive().getPartition(table, partSpec, false);
             } catch (HiveException ex) {
               ptn = null;
-              table = createNewTableMetadataObject(tblDesc);
+              table = createNewTableMetadataObject(tblDesc, true);
               isOldTableValid = false;
             }
           }

http://git-wip-us.apache.org/repos/asf/hive/blob/2bf4fef2/ql/src/test/queries/clientpositive/mm_exim.q
----------------------------------------------------------------------
diff --git a/ql/src/test/queries/clientpositive/mm_exim.q 
b/ql/src/test/queries/clientpositive/mm_exim.q
index d084125..5d82a13 100644
--- a/ql/src/test/queries/clientpositive/mm_exim.q
+++ b/ql/src/test/queries/clientpositive/mm_exim.q
@@ -95,4 +95,12 @@ import table import7_mm from 
'ql/test/data/exports/intermmediate_part';
 select * from import7_mm order by key, p;
 drop table import7_mm;
 
+-- import MM as external
+
+drop table import8_mm;
+import external table import8_mm from 
'ql/test/data/exports/intermmediate_nonpart';
+desc formatted import8_mm;
+select * from import8_mm order by key, p;
+drop table import8_mm;
+
 set hive.exim.test.mode=false;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hive/blob/2bf4fef2/ql/src/test/results/clientpositive/llap/mm_exim.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/llap/mm_exim.q.out 
b/ql/src/test/results/clientpositive/llap/mm_exim.q.out
index 1f40754..8ba815c 100644
--- a/ql/src/test/results/clientpositive/llap/mm_exim.q.out
+++ b/ql/src/test/results/clientpositive/llap/mm_exim.q.out
@@ -554,3 +554,73 @@ POSTHOOK: query: drop table import7_mm
 POSTHOOK: type: DROPTABLE
 POSTHOOK: Input: default@import7_mm
 POSTHOOK: Output: default@import7_mm
+PREHOOK: query: drop table import8_mm
+PREHOOK: type: DROPTABLE
+POSTHOOK: query: drop table import8_mm
+POSTHOOK: type: DROPTABLE
+PREHOOK: query: import external table import8_mm from 
'ql/test/data/exports/intermmediate_nonpart'
+PREHOOK: type: IMPORT
+#### A masked pattern was here ####
+PREHOOK: Output: database:default
+POSTHOOK: query: import external table import8_mm from 
'ql/test/data/exports/intermmediate_nonpart'
+POSTHOOK: type: IMPORT
+#### A masked pattern was here ####
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@import8_mm
+PREHOOK: query: desc formatted import8_mm
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: default@import8_mm
+POSTHOOK: query: desc formatted import8_mm
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: default@import8_mm
+# col_name             data_type               comment             
+key                    int                                         
+p                      int                                         
+                
+# Detailed Table Information            
+Database:              default                  
+#### A masked pattern was here ####
+Retention:             0                        
+#### A masked pattern was here ####
+Table Type:            EXTERNAL_TABLE           
+Table Parameters:               
+       EXTERNAL                TRUE                
+       bucketing_version       2                   
+       numFiles                3                   
+       numRows                 6                   
+       rawDataSize             37                  
+       totalSize               43                  
+#### A masked pattern was here ####
+                
+# Storage Information           
+SerDe Library:         org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe      
 
+InputFormat:           org.apache.hadoop.mapred.TextInputFormat         
+OutputFormat:          
org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat       
+Compressed:            No                       
+Num Buckets:           -1                       
+Bucket Columns:        []                       
+Sort Columns:          []                       
+Storage Desc Params:            
+       serialization.format    1                   
+PREHOOK: query: select * from import8_mm order by key, p
+PREHOOK: type: QUERY
+PREHOOK: Input: default@import8_mm
+#### A masked pattern was here ####
+POSTHOOK: query: select * from import8_mm order by key, p
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@import8_mm
+#### A masked pattern was here ####
+0      456
+10     456
+97     455
+98     455
+100    457
+103    457
+PREHOOK: query: drop table import8_mm
+PREHOOK: type: DROPTABLE
+PREHOOK: Input: default@import8_mm
+PREHOOK: Output: default@import8_mm
+POSTHOOK: query: drop table import8_mm
+POSTHOOK: type: DROPTABLE
+POSTHOOK: Input: default@import8_mm
+POSTHOOK: Output: default@import8_mm

Reply via email to