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

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


The following commit(s) were added to refs/heads/master by this push:
     new 40460be  DRILL-7888: query.json returns an incorrect error message 
when the query fails
40460be is described below

commit 40460be6b958585982c3c7d2b7a35e89ccbfe34a
Author: Volodymyr Vysotskyi <[email protected]>
AuthorDate: Sat Mar 27 16:48:46 2021 +0200

    DRILL-7888: query.json returns an incorrect error message when the query 
fails
---
 .../java/org/apache/drill/exec/ExecConstants.java  |  4 ++
 .../exec/server/options/SystemOptionManager.java   |  1 +
 .../rest/stream/StreamingHttpConnection.java       | 50 +++++++++++++++++++---
 .../java-exec/src/main/resources/drill-module.conf |  1 +
 .../drill/exec/server/rest/TestRestJson.java       | 21 +++++++++
 .../src/test/resources/rest/exception.json         |  3 ++
 .../src/test/resources/rest/verboseExc.json        |  6 +++
 7 files changed, 80 insertions(+), 6 deletions(-)

diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java 
b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
index 43396f9..be44596 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
@@ -1216,6 +1216,10 @@ public final class ExecConstants {
           "the sender to send out its data more rapidly, but you should know 
that it has a risk to OOM when the system is solving parallel " +
           "large queries until we have a more accurate resource manager."));
 
+  public static final String ENABLE_REST_VERBOSE_ERRORS_KEY = 
"drill.exec.http.rest.errors.verbose";
+  public static final OptionValidator ENABLE_REST_VERBOSE_ERRORS = new 
BooleanValidator(ENABLE_REST_VERBOSE_ERRORS_KEY,
+      new OptionDescription("Toggles verbose output of executable error 
messages in rest response"));
+
   // HTTP proxy configuration (Drill config)
   public static final String NET_PROXY_BASE = "drill.exec.net_proxy";
   // HTTP proxy config
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
index eda7d9d..fa3c3f5 100644
--- 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
@@ -257,6 +257,7 @@ public class SystemOptionManager extends BaseOptionManager 
implements AutoClosea
       new OptionDefinition(ClassCompilerSelector.JAVA_COMPILER_JANINO_MAXSIZE),
       new OptionDefinition(ClassCompilerSelector.JAVA_COMPILER_DEBUG),
       new OptionDefinition(ExecConstants.ENABLE_VERBOSE_ERRORS),
+      new OptionDefinition(ExecConstants.ENABLE_REST_VERBOSE_ERRORS),
       new OptionDefinition(ExecConstants.ENABLE_WINDOW_FUNCTIONS_VALIDATOR),
       new OptionDefinition(ExecConstants.SCALAR_REPLACEMENT_VALIDATOR),
       new OptionDefinition(ExecConstants.ENABLE_NEW_TEXT_READER),
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/stream/StreamingHttpConnection.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/stream/StreamingHttpConnection.java
index f283cd0..39575d8 100644
--- 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/stream/StreamingHttpConnection.java
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/stream/StreamingHttpConnection.java
@@ -21,8 +21,11 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.concurrent.CountDownLatch;
 
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.drill.common.exceptions.DrillRuntimeException;
 import org.apache.drill.common.exceptions.UserException;
+import org.apache.drill.common.util.DrillExceptionUtil;
+import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.physical.impl.materialize.QueryDataPackage;
 import org.apache.drill.exec.physical.resultSet.PushResultSetReader;
 import org.apache.drill.exec.physical.resultSet.impl.PushResultSetReaderImpl;
@@ -148,11 +151,8 @@ public class StreamingHttpConnection extends 
BaseWebUserConnection {
    * </code></pre>
    */
   private void emitHeader(TupleMetadata rowSchema) throws IOException {
+    startHeader();
     JsonOutput gen = writer.jsonOutput();
-    gen.writeStartObject();
-    gen.writeFieldName("queryId");
-    gen.writeVarChar(QueryIdHelper.getQueryId(queryId));
-    writeNewline(gen);
     gen.writeFieldName("columns");
     writeColNames(gen, rowSchema);
     writeNewline(gen);
@@ -169,6 +169,14 @@ public class StreamingHttpConnection extends 
BaseWebUserConnection {
     // The array of rows is now open, ready to send batches.
   }
 
+  private void startHeader() throws IOException {
+    JsonOutput gen = writer.jsonOutput();
+    gen.writeStartObject();
+    gen.writeFieldName("queryId");
+    gen.writeVarChar(QueryIdHelper.getQueryId(queryId));
+    writeNewline(gen);
+  }
+
   public void writeNewline(JsonOutput gen) throws IOException {
     gen.flush();
     out.write('\n');
@@ -219,12 +227,42 @@ public class StreamingHttpConnection extends 
BaseWebUserConnection {
    */
   public void finish() throws IOException {
     JsonOutput gen = writer.jsonOutput();
-    gen.writeEndArray();
-    writeNewline(gen);
+    if (batchCount == 0) {
+      startHeader();
+      if 
(getSession().getOptions().getBoolean(ExecConstants.ENABLE_REST_VERBOSE_ERRORS_KEY))
 {
+        emitErrorInfo();
+      }
+    } else {
+      gen.writeEndArray();
+      writeNewline(gen);
+    }
     gen.writeFieldName("queryState");
     gen.writeVarChar(getQueryState());
     writeNewline(gen);
     gen.writeEndObject();
     writeNewline(gen);
   }
+
+  private void emitErrorInfo() throws IOException {
+    JsonOutput gen = writer.jsonOutput();
+    Throwable exception = 
DrillExceptionUtil.getThrowable(error.getException());
+    if (exception != null) {
+      gen.writeFieldName("exception");
+      gen.writeVarChar(exception.getClass().getName());
+      writeNewline(gen);
+      gen.writeFieldName("errorMessage");
+      gen.writeVarChar(exception.getMessage());
+      writeNewline(gen);
+      gen.writeFieldName("stackTrace");
+      gen.writeStartArray();
+      for (String stackFrame : ExceptionUtils.getStackFrames(exception)) {
+        gen.writeVarChar(stackFrame);
+      }
+      gen.writeEndArray();
+    } else {
+      gen.writeFieldName("errorMessage");
+      gen.writeVarChar(error.getMessage());
+    }
+    writeNewline(gen);
+  }
 }
diff --git a/exec/java-exec/src/main/resources/drill-module.conf 
b/exec/java-exec/src/main/resources/drill-module.conf
index 2a58194..a8b1ed3 100644
--- a/exec/java-exec/src/main/resources/drill-module.conf
+++ b/exec/java-exec/src/main/resources/drill-module.conf
@@ -555,6 +555,7 @@ drill.exec.options: {
     exec.enable_bulk_load_table_list: false,
     exec.enable_union_type: false,
     exec.errors.verbose: false,
+    drill.exec.http.rest.errors.verbose: false,
     exec.hashjoin.mem_limit: 0,
     exec.hashjoin.hash_table_calc_type: "LEAN",
     exec.hashjoin.safety_factor: 1.0,
diff --git 
a/exec/java-exec/src/test/java/org/apache/drill/exec/server/rest/TestRestJson.java
 
b/exec/java-exec/src/test/java/org/apache/drill/exec/server/rest/TestRestJson.java
index a204fc3..14a3f43 100644
--- 
a/exec/java-exec/src/test/java/org/apache/drill/exec/server/rest/TestRestJson.java
+++ 
b/exec/java-exec/src/test/java/org/apache/drill/exec/server/rest/TestRestJson.java
@@ -31,6 +31,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.proto.UserBitShared.QueryType;
 import org.apache.drill.exec.store.easy.text.TextFormatPlugin.TextFormatConfig;
+import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableMap;
 import org.apache.drill.test.ClusterFixtureBuilder;
 import org.apache.drill.test.ClusterTest;
 import org.junit.BeforeClass;
@@ -147,6 +148,26 @@ public class TestRestJson extends ClusterTest {
     verifier.verifyFileWithResource(outFile, "failed.json");
   }
 
+  @Test
+  public void testQueryWithException() throws IOException {
+    File outFile = new File(dirTestWatcher.getTmpDir(), "exception.json");
+    String sql = "SELECT * FROM cp.`employee123321123321.json` LIMIT 20";
+    QueryWrapper query = new QueryWrapper(sql, QueryType.SQL.name(),
+        null, null, null, null);
+    runQuery(query, outFile);
+    verifier.verifyFileWithResource(outFile, "exception.json");
+  }
+
+  @Test
+  public void testQueryWithVerboseException() throws IOException {
+    File outFile = new File(dirTestWatcher.getTmpDir(), "verboseExc.json");
+    String sql = "SELECT * FROM cp.`employee123321123321.json` LIMIT 20";
+    QueryWrapper query = new QueryWrapper(sql, QueryType.SQL.name(),
+        null, null, null, 
ImmutableMap.of(ExecConstants.ENABLE_REST_VERBOSE_ERRORS_KEY, "true"));
+    runQuery(query, outFile);
+    verifier.verifyFileWithResource(outFile, "verboseExc.json");
+  }
+
   @SuppressWarnings("unused")
   @Test
   @Ignore("Manual test")
diff --git a/exec/java-exec/src/test/resources/rest/exception.json 
b/exec/java-exec/src/test/resources/rest/exception.json
new file mode 100644
index 0000000..802c411
--- /dev/null
+++ b/exec/java-exec/src/test/resources/rest/exception.json
@@ -0,0 +1,3 @@
+!\{"queryId":"[^"]+"
+,"queryState":"FAILED"
+}
diff --git a/exec/java-exec/src/test/resources/rest/verboseExc.json 
b/exec/java-exec/src/test/resources/rest/verboseExc.json
new file mode 100644
index 0000000..f195b9f
--- /dev/null
+++ b/exec/java-exec/src/test/resources/rest/verboseExc.json
@@ -0,0 +1,6 @@
+!\{"queryId":"[^"]+"
+,"exception":"org.apache.calcite.runtime.CalciteContextException"
+,"errorMessage":"From line 1, column 15 to line 1, column 16: Object 
'employee123321123321.json' not found within 'cp': Object 
'employee123321123321.json' not found within 'cp'"
+!,"stackTrace":\[.*\]
+,"queryState":"FAILED"
+}

Reply via email to