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 cf0d4f171cd HIVE-27957: Better error message for STORED BY (Shohei 
Okumiya, reviewed by Akshat Mathur, Attila Turoczy, Laszlo Bodor)
cf0d4f171cd is described below

commit cf0d4f171cd1147a3bdf3fd8d6c372e4e9758f3e
Author: okumin <[email protected]>
AuthorDate: Wed Apr 10 16:19:36 2024 +0900

    HIVE-27957: Better error message for STORED BY (Shohei Okumiya, reviewed by 
Akshat Mathur, Attila Turoczy, Laszlo Bodor)
    
    Closes #4954
---
 .../apache/hadoop/hive/ql/parse/StorageFormat.java | 52 +++++++++++++++++-----
 .../create_table_stored_by_invalid1.q              |  1 +
 .../create_table_stored_by_invalid2.q              |  1 +
 .../create_table_stored_by_invalid3.q              |  1 +
 .../create_table_stored_by_invalid1.q.out          |  1 +
 .../create_table_stored_by_invalid2.q.out          |  1 +
 .../create_table_stored_by_invalid3.q.out          |  1 +
 7 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/StorageFormat.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/StorageFormat.java
index 50f08ff1f4e..2472ad44ad0 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/StorageFormat.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/StorageFormat.java
@@ -19,9 +19,13 @@ package org.apache.hadoop.hive.ql.parse;
 
 import static org.apache.hadoop.hive.ql.parse.ParseUtils.ensureClassExists;
 
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import java.util.Objects;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.conf.HiveConf;
@@ -48,9 +52,14 @@ public class StorageFormat {
 
   public enum StorageHandlerTypes {
     DEFAULT(),
-    ICEBERG("\'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler\'",
+    ICEBERG("'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'",
         "org.apache.iceberg.mr.hive.HiveIcebergInputFormat", 
"org.apache.iceberg.mr.hive.HiveIcebergOutputFormat");
 
+    private static final List<StorageHandlerTypes> NON_DEFAULT_TYPES = Arrays
+        .stream(values())
+        .filter(type -> type != StorageHandlerTypes.DEFAULT)
+        .collect(Collectors.toList());
+
     private final String className;
     private final String inputFormat;
     private final String outputFormat;
@@ -133,7 +142,7 @@ public class StorageFormat {
             BaseSemanticAnalyzer.readProps((ASTNode) grandChild.getChild(0), 
serdeProps);
             break;
           default:
-            storageHandler = processStorageHandler(grandChild.getText());
+            storageHandler = processStorageHandler(grandChild);
         }
       }
       break;
@@ -157,17 +166,40 @@ public class StorageFormat {
     return true;
   }
 
-  private String processStorageHandler(String name) throws SemanticException {
-    for (StorageHandlerTypes type : StorageHandlerTypes.values()) {
-      if (type.name().equalsIgnoreCase(name)) {
-        name = type.className();
-        inputFormat = type.inputFormat();
-        outputFormat = type.outputFormat();
-        break;
+  private String processStorageHandler(ASTNode node) throws SemanticException {
+    if (node.getType() == HiveParser.StringLiteral) {
+      // e.g. STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
+      try {
+        return 
ensureClassExists(BaseSemanticAnalyzer.unescapeSQLString(node.getText()));
+      } catch (SemanticException e) {
+        throw createUnsupportedStorageHandlerTypeError(node, e);
+      }
+    }
+    if (node.getType() == HiveParser.Identifier) {
+      // e.g. STORED BY ICEBERG
+      for (StorageHandlerTypes type : StorageHandlerTypes.NON_DEFAULT_TYPES) {
+        if (type.name().equalsIgnoreCase(node.getText())) {
+          Objects.requireNonNull(type.className());
+          inputFormat = type.inputFormat();
+          outputFormat = type.outputFormat();
+          return 
ensureClassExists(BaseSemanticAnalyzer.unescapeSQLString(type.className()));
+        }
       }
     }
+    throw createUnsupportedStorageHandlerTypeError(node, null);
+  }
 
-    return ensureClassExists(BaseSemanticAnalyzer.unescapeSQLString(name));
+  private static SemanticException 
createUnsupportedStorageHandlerTypeError(ASTNode node, Throwable cause) {
+    final String supportedTypes = StorageHandlerTypes
+        .NON_DEFAULT_TYPES
+        .stream()
+        .map(Enum::toString)
+        .collect(Collectors.joining(", "));
+    return new SemanticException(String.format(
+        "The storage handler specified in the STORED BY clause is not 
recognized: %s. Please use one of the supported "
+            + "types, which are %s, or provide the Fully Qualified Class Name 
(FQCN) of a valid storage handler.",
+        node.getText(), supportedTypes
+    ), cause);
   }
 
   public void processStorageFormat(String name) throws SemanticException {
diff --git 
a/ql/src/test/queries/clientnegative/create_table_stored_by_invalid1.q 
b/ql/src/test/queries/clientnegative/create_table_stored_by_invalid1.q
new file mode 100644
index 00000000000..6d9af9f4209
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/create_table_stored_by_invalid1.q
@@ -0,0 +1 @@
+CREATE TABLE test (a STRING) STORED BY DEFAULT;
diff --git 
a/ql/src/test/queries/clientnegative/create_table_stored_by_invalid2.q 
b/ql/src/test/queries/clientnegative/create_table_stored_by_invalid2.q
new file mode 100644
index 00000000000..bb42c0c3c9f
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/create_table_stored_by_invalid2.q
@@ -0,0 +1 @@
+CREATE TABLE test (a STRING) STORED BY ORC;
diff --git 
a/ql/src/test/queries/clientnegative/create_table_stored_by_invalid3.q 
b/ql/src/test/queries/clientnegative/create_table_stored_by_invalid3.q
new file mode 100644
index 00000000000..e1ee4cefb1c
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/create_table_stored_by_invalid3.q
@@ -0,0 +1 @@
+CREATE TABLE test (a STRING) STORED BY 'ICEBERG';
diff --git 
a/ql/src/test/results/clientnegative/create_table_stored_by_invalid1.q.out 
b/ql/src/test/results/clientnegative/create_table_stored_by_invalid1.q.out
new file mode 100644
index 00000000000..2271b4d3d79
--- /dev/null
+++ b/ql/src/test/results/clientnegative/create_table_stored_by_invalid1.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException The storage handler specified in the STORED BY 
clause is not recognized: DEFAULT. Please use one of the supported types, which 
are ICEBERG, or provide the Fully Qualified Class Name (FQCN) of a valid 
storage handler.
diff --git 
a/ql/src/test/results/clientnegative/create_table_stored_by_invalid2.q.out 
b/ql/src/test/results/clientnegative/create_table_stored_by_invalid2.q.out
new file mode 100644
index 00000000000..8176a6c0a9d
--- /dev/null
+++ b/ql/src/test/results/clientnegative/create_table_stored_by_invalid2.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException The storage handler specified in the STORED BY 
clause is not recognized: ORC. Please use one of the supported types, which are 
ICEBERG, or provide the Fully Qualified Class Name (FQCN) of a valid storage 
handler.
diff --git 
a/ql/src/test/results/clientnegative/create_table_stored_by_invalid3.q.out 
b/ql/src/test/results/clientnegative/create_table_stored_by_invalid3.q.out
new file mode 100644
index 00000000000..233012e9c21
--- /dev/null
+++ b/ql/src/test/results/clientnegative/create_table_stored_by_invalid3.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException The storage handler specified in the STORED BY 
clause is not recognized: 'ICEBERG'. Please use one of the supported types, 
which are ICEBERG, or provide the Fully Qualified Class Name (FQCN) of a valid 
storage handler.

Reply via email to