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"
+}