tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject tajo git commit: TAJO-1817: Improve SQL parser error message.
Date Fri, 11 Sep 2015 05:00:26 GMT
Repository: tajo
Updated Branches:
  refs/heads/master f5fdc240e -> cc6917804


TAJO-1817: Improve SQL parser error message.

Closes #753


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

Branch: refs/heads/master
Commit: cc6917804a090c277ffe3ad876c59f3f489d9df1
Parents: f5fdc24
Author: Hyunsik Choi <hyunsik@apache.org>
Authored: Fri Sep 11 13:52:05 2015 +0900
Committer: Hyunsik Choi <hyunsik@apache.org>
Committed: Fri Sep 11 13:52:05 2015 +0900

----------------------------------------------------------------------
 CHANGES                                         |  2 +
 .../apache/tajo/exception/SQLSyntaxError.java   |  4 ++
 .../apache/tajo/parser/sql/TestSQLAnalyzer.java | 58 ++++++++++++-----
 .../TestSQLAnalyzer/errors/identifier1.sql      |  9 +++
 .../TestSQLAnalyzer/errors/in_subquery_1.sql    |  7 +++
 .../queries/TestSQLAnalyzer/errors/join_1.sql   | 13 ++++
 .../TestSQLAnalyzer/errors/identifier1.result   |  3 +
 .../TestSQLAnalyzer/errors/in_subquery_1.result |  3 +
 .../TestSQLAnalyzer/errors/join_1.result        |  3 +
 .../TestTajoCliNegatives/testQuerySyntax.result |  6 +-
 .../org/apache/tajo/parser/sql/SQLAnalyzer.java | 39 +++++++-----
 .../tajo/parser/sql/SQLErrorListener.java       |  4 +-
 .../tajo/parser/sql/SQLErrorStrategy.java       | 66 --------------------
 .../apache/tajo/parser/sql/SQLParseError.java   |  9 ++-
 .../apache/tajo/jdbc/TestTajoJdbcNegative.java  | 39 ++++++++++++
 .../org/apache/tajo/parser/sql/SQLParser.g4     |  3 +-
 16 files changed, 162 insertions(+), 106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index e45b16e..771c1bd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -36,6 +36,8 @@ Release 0.11.0 - unreleased
 
   IMPROVEMENT
 
+    TAJO-1817: Improve SQL parser error message. (hyunsik)
+
     TAJO-1825: Remove zero length fragments when file length is zero. (jinho)
 
     TAJO-1828: tajo-daemon scripts should kill process after process can not 

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-common/src/main/java/org/apache/tajo/exception/SQLSyntaxError.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/exception/SQLSyntaxError.java b/tajo-common/src/main/java/org/apache/tajo/exception/SQLSyntaxError.java
index 8860321..36b6c0d 100644
--- a/tajo-common/src/main/java/org/apache/tajo/exception/SQLSyntaxError.java
+++ b/tajo-common/src/main/java/org/apache/tajo/exception/SQLSyntaxError.java
@@ -22,9 +22,13 @@ package org.apache.tajo.exception;
 import org.apache.tajo.error.Errors;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.ReturnState;
 
+/**
+ * Exception for SQL Syntax errors
+ */
 public class SQLSyntaxError extends TajoException {
   private static final long serialVersionUID = 5388279335175632067L;
 
+  @SuppressWarnings("unused")
   public SQLSyntaxError(ReturnState state) {
     super(state);
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/java/org/apache/tajo/parser/sql/TestSQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/parser/sql/TestSQLAnalyzer.java
b/tajo-core-tests/src/test/java/org/apache/tajo/parser/sql/TestSQLAnalyzer.java
index e6eb71f..f3c302a 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/parser/sql/TestSQLAnalyzer.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/parser/sql/TestSQLAnalyzer.java
@@ -30,6 +30,7 @@ import org.apache.hadoop.fs.Path;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.exception.SQLSyntaxError;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.util.FileUtil;
 import org.apache.tajo.util.Pair;
@@ -54,19 +55,9 @@ import static org.junit.Assert.*;
  */
 public class TestSQLAnalyzer {
   @Rule public TestName name = new TestName();
-
-  public static Expr parseQuery(String sql) {
-    ANTLRInputStream input = new ANTLRInputStream(sql);
-    SQLLexer lexer = new SQLLexer(input);
-    CommonTokenStream tokens = new CommonTokenStream(lexer);
-
-    SQLParser parser = new SQLParser(tokens);
-    parser.setErrorHandler(new BailErrorStrategy());
-    parser.setBuildParseTree(true);
-
-    SQLAnalyzer visitor = new SQLAnalyzer();
-    SQLParser.SqlContext context = parser.sql();
-    return visitor.visitSql(context);
+  final static SQLAnalyzer analyzer = new SQLAnalyzer();
+  public static Expr parseQuery(String sql) throws SQLSyntaxError {
+    return analyzer.parse(sql);
   }
 
   public Collection<File> getResourceFiles(String subdir) throws URISyntaxException,
IOException {
@@ -134,6 +125,38 @@ public class TestSQLAnalyzer {
         fail("Parsing '" + pair.getFirst() + "' failed, its cause: " + t.getMessage());
       }
     }
+    System.out.flush();
+  }
+
+  /**
+   * In order to add more unit tests, please add SQL files into resources/queries/TestSQLAnalyzer/errors.
+   * This test just checkes if the error messages caused by SQL parsing errors
+   *
+   * @throws IOException
+   * @throws URISyntaxException
+   */
+  @Test
+  public void testErrorMessages() throws IOException, URISyntaxException {
+    for (Pair<String, String> pair : getFileContents("errors")) {
+
+      String fileName = pair.getFirst().split("\\.")[0];
+      String expectedResult = "";
+
+      try {
+        expectedResult = FileUtil.readTextFileFromResource("results/TestSQLAnalyzer/errors/"
+ fileName + ".result");
+      } catch (FileNotFoundException fnfe) {
+      }
+
+      try {
+        Expr expr = parseQuery(pair.getSecond());
+        System.out.println(expr);
+        fail(pair.getFirst() + " must be failed.");
+      } catch (SQLSyntaxError e) {
+        assertEquals("Error message is different from " + fileName + ".result", expectedResult,
e.getMessage());
+      }
+      System.out.println(pair.getFirst() + " test passed...");
+    }
+    System.out.flush();
   }
 
   /**
@@ -148,7 +171,12 @@ public class TestSQLAnalyzer {
   @Test
   public void testGeneratedAlgebras() throws IOException, URISyntaxException {
     for (Pair<String, String> pair : getFileContents(".")) {
-      Expr expr = parseQuery(pair.getSecond());
+      Expr expr = null;
+      try {
+        expr = parseQuery(pair.getSecond());
+      } catch (SQLSyntaxError t) {
+        fail(t.getMessage());
+      }
 
       String expectedResult = null;
       String fileName = null;
@@ -165,6 +193,7 @@ public class TestSQLAnalyzer {
           expectedResult.trim(), expr.toJson().trim());
       System.out.println(pair.getFirst() + " test passed..");
     }
+    System.out.flush();
   }
 
   private static Expr parseExpr(String sql) {
@@ -194,6 +223,7 @@ public class TestSQLAnalyzer {
       testExprs(pair.getFirst(), pair.getSecond());
       System.out.println(pair.getFirst() + " test passed..");
     }
+    System.out.flush();
   }
 
   private void testExprs(String file, String fileContents) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/identifier1.sql
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/identifier1.sql
b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/identifier1.sql
new file mode 100644
index 0000000..3cca6a0
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/identifier1.sql
@@ -0,0 +1,9 @@
+SELECT x,y,z FROM (
+  SELECT
+    l,
+    K
+  FROM
+    TTT
+  1
+) XX;
+

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/in_subquery_1.sql
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/in_subquery_1.sql
b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/in_subquery_1.sql
new file mode 100644
index 0000000..8102e1f
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/in_subquery_1.sql
@@ -0,0 +1,7 @@
+select
+  *
+from
+  lineitem
+where l_orderkey in (
+  select xxx 1from inner_table
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/join_1.sql
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/join_1.sql
b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/join_1.sql
new file mode 100644
index 0000000..11c66ce
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/errors/join_1.sql
@@ -0,0 +1,13 @@
+SELECT
+  d_date_sk ss_sold_date_sk
+FROM s_purchase
+  LEFTT OUTER JOIN customer ON (purc_customer_id = c_customer_id)
+  LEFT OUTER JOIN store ON (purc_store_id = s_store_id)
+  LEFT OUTER JOIN date_dim ON (cast(purc_purchase_date as date) = d_date)
+  LEFT OUTER JOIN time_dim ON (PURC_PURCHASE_TIME = t_time)
+  JOIN s_purchase_lineitem ON (purc_purchase_id = plin_purchase_id)
+  LEFT OUTER JOIN promotion ON plin_promotion_id = p_promo_id
+  LEFT OUTER JOIN item ON plin_item_id = i_item_id
+WHERE purc_purchase_id = plin_purchase_id
+  AND i_rec_end_date is NULL
+  AND s_rec_end_date is NULL;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/identifier1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/identifier1.result
b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/identifier1.result
new file mode 100644
index 0000000..7e17fb2
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/identifier1.result
@@ -0,0 +1,3 @@
+ERROR: syntax error at or near "1"
+LINE 7:   1
+          ^
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/in_subquery_1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/in_subquery_1.result
b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/in_subquery_1.result
new file mode 100644
index 0000000..1c6a429
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/in_subquery_1.result
@@ -0,0 +1,3 @@
+ERROR: syntax error at or near "1"
+LINE 6:   select xxx 1from inner_table
+                     ^
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/join_1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/join_1.result
b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/join_1.result
new file mode 100644
index 0000000..fd0cb94
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/errors/join_1.result
@@ -0,0 +1,3 @@
+ERROR: syntax error at or near "OUTER"
+LINE 4:   LEFTT OUTER JOIN customer ON (purc_customer_id = c_customer_id)
+                ^^^^^
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core-tests/src/test/resources/results/TestTajoCliNegatives/testQuerySyntax.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestTajoCliNegatives/testQuerySyntax.result
b/tajo-core-tests/src/test/resources/results/TestTajoCliNegatives/testQuerySyntax.result
index 86b0b59..5db9b3e 100644
--- a/tajo-core-tests/src/test/resources/results/TestTajoCliNegatives/testQuerySyntax.result
+++ b/tajo-core-tests/src/test/resources/results/TestTajoCliNegatives/testQuerySyntax.result
@@ -1,3 +1,3 @@
-ERROR: mismatched input '-' expecting {<EOF>, EXCEPT, GROUP, HAVING, INTERSECT, LIMIT,
ORDER, UNION, WHERE, WINDOW, ';', ','}
-LINE 1:21 select * from unknown-table
-                               ^
+ERROR: syntax error at or near "-"
+LINE 1: select * from unknown-table
+                             ^

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
index 793cb1c..4e3e369 100644
--- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
+++ b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
@@ -35,6 +35,7 @@ import org.apache.tajo.algebra.DataTypeExpr.MapType;
 import org.apache.tajo.algebra.LiteralValue.LiteralType;
 import org.apache.tajo.algebra.Sort.SortSpec;
 import org.apache.tajo.exception.SQLSyntaxError;
+import org.apache.tajo.exception.TajoInternalError;
 import org.apache.tajo.exception.TajoRuntimeException;
 import org.apache.tajo.parser.sql.SQLParser.*;
 import org.apache.tajo.storage.StorageConstants;
@@ -52,21 +53,29 @@ import static org.apache.tajo.parser.sql.SQLParser.*;
 public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
 
   public Expr parse(String sql) throws SQLSyntaxError {
-    ANTLRInputStream input = new ANTLRInputStream(sql);
-    SQLLexer lexer = new SQLLexer(input);
-    CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+    final ANTLRInputStream input = new ANTLRInputStream(sql);
+    final SQLLexer lexer = new SQLLexer(input);
+    lexer.removeErrorListeners();
+    lexer.addErrorListener(new SQLErrorListener());
+
+    final CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+
+    final SQLParser parser = new SQLParser(tokens);
+    parser.removeErrorListeners();
+    parser.addErrorListener(new SQLErrorListener());
+    parser.setBuildParseTree(true);
+
     SqlContext context;
     try {
-      SQLParser parser = new SQLParser(tokens);
-      parser.setBuildParseTree(true);
-      parser.removeErrorListeners();
-
-      parser.setErrorHandler(new SQLErrorStrategy());
-      parser.addErrorListener(new SQLErrorListener());
       context = parser.sql();
     } catch (SQLParseError e) {
       throw new SQLSyntaxError(e.getMessage());
+    } catch (Throwable t) {
+      throw new TajoInternalError(t.getMessage());
     }
+
     return visitSql(context);
   }
 
@@ -118,7 +127,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
       return new SetSession(SessionVars.TIMEZONE.name(), value);
 
     } else {
-      throw new TajoRuntimeException(new SQLSyntaxError("Unsupported session statement"));
+      throw new TajoInternalError("Invalid session statement");
     }
   }
 
@@ -970,7 +979,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
         return OpType.Minus;
 
       default:
-        throw new RuntimeException("Unknown Token Id: " + tokenId);
+        throw new TajoInternalError("unknown Token Id: " + tokenId);
     }
   }
 
@@ -1022,7 +1031,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
       } else if (checkIfExist(matcher.REGEXP()) || checkIfExist(matcher.RLIKE())) {
         return new PatternMatchPredicate(OpType.Regexp, not, predicand, pattern);
       } else {
-        throw new TajoRuntimeException(new SQLSyntaxError("Unsupported predicate: " + matcher.getText()));
+        throw new TajoInternalError("unknown pattern matching predicate: " + matcher.getText());
       }
     } else if (checkIfExist(ctx.pattern_matcher().regex_matcher())) {
       Regex_matcherContext matcher = ctx.pattern_matcher().regex_matcher();
@@ -1035,10 +1044,10 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr>
{
       } else if (checkIfExist(matcher.Not_Similar_To_Case_Insensitive())) {
         return new PatternMatchPredicate(OpType.Regexp, true, predicand, pattern, true);
       } else {
-        throw new TajoRuntimeException(new SQLSyntaxError("Unsupported predicate: " + matcher.getText()));
+        throw new TajoInternalError("Unsupported predicate: " + matcher.getText());
       }
     } else {
-      throw new TajoRuntimeException(new SQLSyntaxError("Unsupported predicate: " + ctx.pattern_matcher().getText()));
+      throw new TajoInternalError("invalid pattern matching predicate: " + ctx.pattern_matcher().getText());
     }
   }
 
@@ -1417,7 +1426,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     } else if (checkIfExist(ctx.column_partitions())) { // For Column Partition (Hive Style)
       return new CreateTable.ColumnPartition(getDefinitions(ctx.column_partitions().table_elements()));
     } else {
-      throw new TajoRuntimeException(new SQLSyntaxError("Invalid Partition Type: " + ctx.toStringTree()));
+      throw new TajoInternalError("invalid partition type: " + ctx.toStringTree());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorListener.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorListener.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorListener.java
index e960844..4c80f4c 100644
--- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorListener.java
+++ b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorListener.java
@@ -22,6 +22,7 @@ import org.antlr.v4.runtime.*;
 import org.apache.commons.lang.StringUtils;
 
 public class SQLErrorListener extends BaseErrorListener {
+
   public void syntaxError(Recognizer<?, ?> recognizer,
                           Object offendingSymbol,
                           int line, int charPositionInLine,
@@ -33,6 +34,7 @@ public class SQLErrorListener extends BaseErrorListener {
     String[] lines = StringUtils.splitPreserveAllTokens(input, '\n');
     String errorLine = lines[line - 1];
 
-    throw new SQLParseError(token, line, charPositionInLine, msg, errorLine);
+    String simpleMessage = "syntax error at or near \"" + token.getText() + "\"";
+    throw new SQLParseError(token, line, charPositionInLine, simpleMessage, errorLine);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorStrategy.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorStrategy.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorStrategy.java
deleted file mode 100644
index 236b854..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLErrorStrategy.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.parser.sql;
-
-import org.antlr.v4.runtime.*;
-import org.antlr.v4.runtime.misc.NotNull;
-
-public class SQLErrorStrategy extends DefaultErrorStrategy {
-
-  @Override
-  public void reportError(Parser recognizer, RecognitionException e) {
-    // if we've already reported an error and have not matched a token
-    // yet successfully, don't report any errors.
-    if (inErrorRecoveryMode(recognizer)) {
-      return; // don't report spurious errors
-    }
-    beginErrorCondition(recognizer);
-    if (e instanceof NoViableAltException) {
-      reportNoViableAltException(recognizer, (NoViableAltException) e);
-    } else if (e instanceof InputMismatchException) {
-      reportInputMismatchException(recognizer, (InputMismatchException) e);
-    } else if (e instanceof FailedPredicateException) {
-      reportFailedPredicate(recognizer, (FailedPredicateException) e);
-    } else {
-      recognizer.notifyErrorListeners(e.getOffendingToken(), e.getMessage(), e);
-    }
-  }
-
-  protected void reportNoViableAltException(@NotNull Parser recognizer, @NotNull NoViableAltException
e) {
-    TokenStream tokens = recognizer.getInputStream();
-    String msg;
-    Token token = e.getStartToken();
-    if (tokens != null) {
-      if (tokens.LT(-1) != null && token.getType() == Token.EOF) {
-        token = tokens.LT(-1);
-      }
-      msg = "syntax error at or near " + getTokenErrorDisplay(token);
-    } else {
-      msg = "no viable alternative at input " + escapeWSAndQuote("<unknown input>");
-    }
-    recognizer.notifyErrorListeners(token, msg, e);
-  }
-
-  protected void reportInputMismatchException(@NotNull Parser recognizer,
-                                              @NotNull InputMismatchException e) {
-    String msg = "mismatched input " + getTokenErrorDisplay(e.getOffendingToken()) +
-        " expecting " + e.getExpectedTokens().toString(recognizer.getTokenNames());
-    recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e);
-  }
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLParseError.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLParseError.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLParseError.java
index f0568a5..ef07cba 100644
--- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLParseError.java
+++ b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLParseError.java
@@ -22,6 +22,9 @@ package org.apache.tajo.parser.sql;
 import org.antlr.v4.runtime.Token;
 import org.apache.commons.lang.StringUtils;
 
+/**
+ * Exception that represents a kind of SQL syntax error caused by the parser layer
+ */
 public class SQLParseError extends RuntimeException {
   private String header;
   private String errorLine;
@@ -58,14 +61,10 @@ public class SQLParseError extends RuntimeException {
     return detailedMessage;
   }
 
-  public String getMessageHeader(){
-    return this.header;
-  }
-
   private String getDetailedMessageWithLocation() {
     StringBuilder sb = new StringBuilder();
     int displayLimit = 80;
-    String queryPrefix = "LINE " + line + ":" + charPositionInLine + " ";
+    String queryPrefix = "LINE " + line + ":" + " ";
     String prefixPadding = StringUtils.repeat(" ", queryPrefix.length());
     String locationString;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
index 232292b..c1414dc 100644
--- a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
+++ b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
@@ -116,6 +116,45 @@ public class TestTajoJdbcNegative extends QueryTestCaseBase {
   }
 
   @Test
+  public void testSyntaxErrorOnExecuteUpdate() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
+    try (Statement stmt = conn.createStatement()) {
+      stmt.executeUpdate("CREATE TABLE \n1table123u8sd ( name RECORD(last TEXT, first TEXT)
)");
+      fail("Must be failed");
+    } catch (SQLException s) {
+      assertEquals(toSQLState(ResultCode.SYNTAX_ERROR), s.getSQLState());
+      assertEquals(
+          "ERROR: syntax error at or near \"1\"\n" +
+          "LINE 2: 1table123u8sd ( name RECORD(last TEXT, first TEXT) )\n" +
+          "        ^", s.getMessage());
+    }
+  }
+
+  @Test
+  public void testSyntaxErrorOnExecuteQuery() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
+    try (Statement stmt = conn.createStatement()) {
+      try (ResultSet result = stmt.executeQuery("SELECT\n*\nFROM_ LINEITEM")) {
+        fail("Must be failed");
+      } catch (SQLException s) {
+        assertEquals(toSQLState(ResultCode.SYNTAX_ERROR), s.getSQLState());
+        assertEquals(
+            "ERROR: syntax error at or near \"from_\"\n" +
+            "LINE 3: FROM_ LINEITEM\n" +
+            "        ^^^^^", s.getMessage());
+      }
+    }
+  }
+
+  @Test
   public void testImmediateException() throws Exception {
     String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
         DEFAULT_DATABASE_NAME);

http://git-wip-us.apache.org/repos/asf/tajo/blob/cc691780/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4 b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
index 41de218..87b897d 100644
--- a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
+++ b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
@@ -53,8 +53,7 @@ statement
 session_statement
   : SET CATALOG dbname = identifier
   | SET TIME ZONE (TO | EQUAL)? (Character_String_Literal | signed_numerical_literal | DEFAULT)
-  | SET (SESSION)? name=identifier (TO | EQUAL)?
-    (Character_String_Literal | signed_numerical_literal | boolean_literal | DEFAULT)
+  | SET (SESSION)? name=identifier (TO | EQUAL)?  (Character_String_Literal | signed_numerical_literal
| boolean_literal | DEFAULT)
   | RESET name=identifier
   ;
 


Mime
View raw message