From 0a3ed9fa0173d42a3222d9ed7dd714ac4ab7e79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=98=95=EC=A4=80?= Date: Wed, 28 May 2014 23:01:29 +0900 Subject: [PATCH] TAJO-793: CLI should be able to exit when single query is failed. --- .../cli/DefaultTajoCliOutputFormatter.java | 6 +++++ .../java/org/apache/tajo/cli/TajoCli.java | 25 ++++++++++++++++++- .../java/org/apache/tajo/conf/TajoConf.java | 1 + .../java/org/apache/tajo/cli/TestTajoCli.java | 17 +++++++++++++ .../TestTajoCli/testStopWhenError.result | 5 ++++ 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tajo-core/src/test/resources/results/TestTajoCli/testStopWhenError.result diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/DefaultTajoCliOutputFormatter.java b/tajo-client/src/main/java/org/apache/tajo/cli/DefaultTajoCliOutputFormatter.java index a619981d22..62736b5ea5 100644 --- a/tajo-client/src/main/java/org/apache/tajo/cli/DefaultTajoCliOutputFormatter.java +++ b/tajo-client/src/main/java/org/apache/tajo/cli/DefaultTajoCliOutputFormatter.java @@ -128,6 +128,7 @@ public void printResult(PrintWriter sout, InputStream sin, TableDesc tableDesc, @Override public void printNoResult(PrintWriter sout) { sout.println("(0 rows)"); + sout.flush(); } @Override @@ -141,6 +142,7 @@ public void printProgress(PrintWriter sout, QueryStatus status) { @Override public void printMessage(PrintWriter sout, String message) { sout.println(message); + sout.flush(); } @Override @@ -149,16 +151,19 @@ public void printErrorMessage(PrintWriter sout, Throwable t) { if (printErrorTrace) { sout.println(ExceptionUtils.getStackTrace(t)); } + sout.flush(); } @Override public void printErrorMessage(PrintWriter sout, String message) { sout.println(parseErrorMessage(message)); + sout.flush(); } @Override public void printKilledMessage(PrintWriter sout, QueryId queryId) { sout.println(TajoCli.KILL_PREFIX + queryId); + sout.flush(); } @Override @@ -171,6 +176,7 @@ public void printErrorMessage(PrintWriter sout, QueryStatus status) { if (printErrorTrace && status.getErrorTrace() != null && !status.getErrorTrace().isEmpty()) { sout.println(status.getErrorTrace()); } + sout.flush(); } public static String parseErrorMessage(String message) { diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java b/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java index 85787caa38..18def2aee6 100644 --- a/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java +++ b/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java @@ -64,6 +64,8 @@ public class TajoCli { private TajoCliOutputFormatter outputFormatter; + private boolean wasError = false; + private static final Class [] registeredCommands = { DescTableCommand.class, DescFunctionCommand.class, @@ -315,7 +317,7 @@ public int runShell() throws Exception { if (line.equals("")) { continue; } - + wasError = false; if (line.startsWith("{")) { executeJsonQuery(line); } else { @@ -340,6 +342,10 @@ private void executeParsedResults(Collection parsedResults) throws } else { executeQuery(parsedResult.getStatement()); } + + if (wasError && context.getConf().getBoolVar(ConfVars.CLI_STOP_ERROR)) { + break; + } } } @@ -351,6 +357,7 @@ public int executeMetaCommand(String line) throws Exception { TajoShellCommand invoked = commands.get(arguments[0]); if (invoked == null) { printInvalidCommand(arguments[0]); + wasError = true; return -1; } @@ -358,13 +365,19 @@ public int executeMetaCommand(String line) throws Exception { invoked.invoke(arguments); } catch (IllegalArgumentException ige) { outputFormatter.printErrorMessage(sout, ige); + wasError = true; return -1; } catch (Exception e) { outputFormatter.printErrorMessage(sout, e); + wasError = true; return -1; } finally { context.getOutput().flush(); } + + if (wasError && context.getConf().getBoolVar(ConfVars.CLI_STOP_ERROR)) { + break; + } } return 0; @@ -375,6 +388,7 @@ private void executeJsonQuery(String json) throws ServiceException { ClientProtos.SubmitQueryResponse response = client.executeQueryWithJson(json); if (response == null) { outputFormatter.printErrorMessage(sout, "response is null"); + wasError = true; } else if (response.getResultCode() == ClientProtos.ResultCode.OK) { if (response.getIsForwarded()) { QueryId queryId = new QueryId(response.getQueryId()); @@ -382,6 +396,7 @@ private void executeJsonQuery(String json) throws ServiceException { } else { if (!response.hasTableDesc() && !response.hasResultSet()) { outputFormatter.printMessage(sout, "OK"); + wasError = true; } else { localQueryCompleted(response, startTime); } @@ -389,6 +404,7 @@ private void executeJsonQuery(String json) throws ServiceException { } else { if (response.hasErrorMessage()) { outputFormatter.printErrorMessage(sout, response.getErrorMessage()); + wasError = true; } } } @@ -398,6 +414,7 @@ private void executeQuery(String statement) throws ServiceException { ClientProtos.SubmitQueryResponse response = client.executeQuery(statement); if (response == null) { outputFormatter.printErrorMessage(sout, "response is null"); + wasError = true; } else if (response.getResultCode() == ClientProtos.ResultCode.OK) { if (response.getIsForwarded()) { QueryId queryId = new QueryId(response.getQueryId()); @@ -412,6 +429,7 @@ private void executeQuery(String statement) throws ServiceException { } else { if (response.hasErrorMessage()) { outputFormatter.printErrorMessage(sout, response.getErrorMessage()); + wasError = true; } } } @@ -433,6 +451,7 @@ private void localQueryCompleted(ClientProtos.SubmitQueryResponse response, long } } catch (Throwable t) { outputFormatter.printErrorMessage(sout, t); + wasError = true; } finally { if (res != null) { try { @@ -481,8 +500,10 @@ private void waitForQueryCompleted(QueryId queryId) { if (status.getState() == QueryState.QUERY_ERROR || status.getState() == QueryState.QUERY_FAILED) { outputFormatter.printErrorMessage(sout, status); + wasError = true; } else if (status.getState() == QueryState.QUERY_KILLED) { outputFormatter.printKilledMessage(sout, queryId); + wasError = true; } else { if (status.getState() == QueryState.QUERY_SUCCEEDED) { float responseTime = ((float)(status.getFinishTime() - status.getSubmitTime()) / 1000.0f); @@ -499,6 +520,7 @@ private void waitForQueryCompleted(QueryId queryId) { } } catch (Throwable t) { outputFormatter.printErrorMessage(sout, t); + wasError = true; } finally { if (res != null) { try { @@ -514,6 +536,7 @@ private void waitForQueryCompleted(QueryId queryId) { } public int executeScript(String script) throws Exception { + wasError = false; List results = SimpleParser.parseScript(script); executeParsedResults(results); return 0; diff --git a/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java b/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java index 9e61967318..78ac1aa8d9 100644 --- a/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java +++ b/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java @@ -325,6 +325,7 @@ public static enum ConfVars { CLI_PRINT_ERROR_TRACE("tajo.cli.print.error.trace", true), CLI_OUTPUT_FORMATTER_CLASS("tajo.cli.output.formatter", "org.apache.tajo.cli.DefaultTajoCliOutputFormatter"), CLI_NULL_CHAR("tajo.cli.nullchar", ""), + CLI_STOP_ERROR("tajo.cli.stop.error", false), //TIME & DATE TAJO_TIMEZONE("tajo.timezone", System.getProperty("user.timezone")), diff --git a/tajo-core/src/test/java/org/apache/tajo/cli/TestTajoCli.java b/tajo-core/src/test/java/org/apache/tajo/cli/TestTajoCli.java index a49f23b89f..9c6445cf13 100644 --- a/tajo-core/src/test/java/org/apache/tajo/cli/TestTajoCli.java +++ b/tajo-core/src/test/java/org/apache/tajo/cli/TestTajoCli.java @@ -275,6 +275,23 @@ private void assertOutputResult(String expectedResultFile, String actual, String assertEquals(expectedResult, actual); } + @Test + public void testStopWhenError() throws Exception { + TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration(); + tajoConf.setVar(ConfVars.CLI_OUTPUT_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + tajoCli = new TajoCli(tajoConf, new String[]{}, System.in, out); + tajoCli.executeMetaCommand("\\set tajo.cli.stop.error true"); + + tajoCli.executeScript("select count(*) from lineitem; " + + "select count(*) from lineitem2; " + + "select count(*) from orders"); + + String consoleResult = new String(out.toByteArray()); + assertOutputResult(consoleResult); + } + public static class TajoCliOutputTestFormatter extends DefaultTajoCliOutputFormatter { @Override protected String getResponseTimeReadable(float responseTime) { diff --git a/tajo-core/src/test/resources/results/TestTajoCli/testStopWhenError.result b/tajo-core/src/test/resources/results/TestTajoCli/testStopWhenError.result new file mode 100644 index 0000000000..183e6c5d79 --- /dev/null +++ b/tajo-core/src/test/resources/results/TestTajoCli/testStopWhenError.result @@ -0,0 +1,5 @@ +?count +------------------------------- +5 +(1 rows, , 2 B selected) +ERROR: relation "default.lineitem2" does not exist