tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject git commit: TAJO-86: Improved error messages in query analyzer. (jinho)
Date Thu, 18 Jul 2013 01:43:40 GMT
Updated Branches:
  refs/heads/master 7653c7431 -> 592313aab


TAJO-86: Improved error messages in query analyzer. (jinho)


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

Branch: refs/heads/master
Commit: 592313aab53d65979e8d3dfa533c94d4cb37caac
Parents: 7653c74
Author: jinossy <jinossy@gmail.com>
Authored: Thu Jul 18 10:41:50 2013 +0900
Committer: jinossy <jinossy@gmail.com>
Committed: Thu Jul 18 10:41:50 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |  2 +
 .../org/apache/tajo/engine/parser/SQLLexer.g    | 19 +++++-
 .../org/apache/tajo/engine/parser/SQLParser.g   | 37 +++++++++---
 .../tajo/engine/parser/QueryAnalyzer.java       |  3 +-
 .../engine/query/exception/TQLParseError.java   | 17 ++++++
 .../engine/query/exception/TQLSyntaxError.java  | 61 +++++++++++++++++---
 6 files changed, 122 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/592313aa/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 0048e51..330280a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,6 +10,8 @@ Release 0.2.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-86: Improved error messages in query analyzer. (jinho)
+
     TAJO-85: Add an method of create(DataType, byte[]) to DatumFactory. (jihoon)
 
     TAJO-79: Refactor and Improve TajoCli. (hyunsik)

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/592313aa/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLLexer.g
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLLexer.g
b/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLLexer.g
index 3360d7c..48aa8de 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLLexer.g
+++ b/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLLexer.g
@@ -26,8 +26,23 @@ import org.apache.tajo.engine.query.exception.TQLParseError;
 
 @members {
    @Override
-   public void reportError(RecognitionException e) {
-    throw new TQLParseError(getErrorHeader(e));
+   public String getErrorMessage(RecognitionException e, String[] tokenNames) {
+    String msg = null;
+
+    if (e instanceof NoViableAltException) {
+      msg = "character " + getCharErrorDisplay(e.c) + " not supported here";
+    } else {
+      msg = super.getErrorMessage(e, tokenNames);
+    }
+    return msg;
+   }
+
+   @Override
+   public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
+
+     String hdr = getErrorHeader(e);
+     String msg = getErrorMessage(e, tokenNames);
+     throw new TQLParseError(hdr + ":" + msg);
    }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/592313aa/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLParser.g
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLParser.g
b/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLParser.g
index 96b2bf0..ea4d633 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLParser.g
+++ b/tajo-core/tajo-core-backend/src/main/antlr3/org/apache/tajo/engine/parser/SQLParser.g
@@ -70,19 +70,42 @@ import org.apache.tajo.engine.query.exception.TQLParseError;
 
 @members {
    @Override
-   public void reportError(RecognitionException e) {
-     throw new TQLParseError(getErrorHeader(e));
+   public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
+     int pos = 0;
+     int line = 0;
+     if (e.charPositionInLine < 0 && input.LT(-1) != null) {
+        Token t = input.LT(-1);
+        line = t.getLine();
+        pos = t.getCharPositionInLine();
+     } else {
+        line = e.line;
+        pos = e.charPositionInLine;
+     }
+     String msg = getErrorMessage(e, tokenNames);
+     throw new TQLParseError(msg, line, pos);
    }
 
    @Override
-   public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
-     String hdr = getErrorHeader(e);
-     String msg = getErrorMessage(e, tokenNames);
-     throw new TQLParseError(hdr + ":" + msg);
+   public String getErrorMessage(RecognitionException e, String[] tokenNames) {
+     String msg = null;
+
+     if (e instanceof NoViableAltException) {
+       msg = "syntax error at or near " + getTokenErrorDisplay(e.token) + (input.LT(2) !=
null ? " " + getTokenErrorDisplay(input.LT(2)) : "")
+       + (input.LT(3) != null ? " " + getTokenErrorDisplay(input.LT(3)) : "");
+      } else if (e instanceof MismatchedTokenException) {
+       MismatchedTokenException mte = (MismatchedTokenException) e;
+       msg = super.getErrorMessage(e, tokenNames) + (input.LT(-1) == null ? "" : " near '"
+ input.LT(-1).getText()) + "'";
+      } else if (e instanceof FailedPredicateException) {
+       FailedPredicateException fpe = (FailedPredicateException) e;
+       msg = "Failed to recognize predicate '" + fpe.token.getText() + "'. Failed rule: '"
+ fpe.ruleName + "'";
+      }else {
+       msg = super.getErrorMessage(e, tokenNames);
+      }
+
+      return msg;
    }
 }
 
-
 /*
 ===============================================================================
   <data types>

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/592313aa/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/QueryAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/QueryAnalyzer.java
b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/QueryAnalyzer.java
index fa5475a..6238300 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/QueryAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/QueryAnalyzer.java
@@ -73,7 +73,7 @@ public final class QueryAnalyzer {
       ParseTree parseTree = parseQueryTree(context,ast);
       context.setParseTree(parseTree);
     } catch (TQLParseError e) {
-      throw new TQLSyntaxError(query, e.getMessage());
+      throw new TQLSyntaxError(query, e);
     }
 
     if (LOG.isDebugEnabled()) {
@@ -944,6 +944,7 @@ public final class QueryAnalyzer {
   private static CommonTree parseTree(final String query) {
     ANTLRStringStream input = new ANTLRStringStream(query);
     SQLLexer lexer = new SQLLexer(input);
+
     CommonTokenStream tokens = new CommonTokenStream(lexer);
     SQLParser parser = new SQLParser(tokens);
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/592313aa/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLParseError.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLParseError.java
b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLParseError.java
index b9db4d3..5f9258e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLParseError.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLParseError.java
@@ -21,7 +21,24 @@ package org.apache.tajo.engine.query.exception;
 
 @SuppressWarnings("UnusedDeclaration")
 public class TQLParseError extends RuntimeException {
+  private int errorLine;
+  private int errorPosition;
+
   public TQLParseError(String parseErrorMessage) {
     super(parseErrorMessage);
   }
+
+  public TQLParseError(String parseErrorMessage, int line, int position) {
+    super(parseErrorMessage);
+    this.errorLine = line;
+    this.errorPosition = position;
+  }
+
+  public int getErrorPosition(){
+    return this.errorPosition;
+  }
+
+  public int getErrorLine(){
+    return this.errorLine;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/592313aa/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLSyntaxError.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLSyntaxError.java
b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLSyntaxError.java
index b1fbc5b..80a767f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLSyntaxError.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/exception/TQLSyntaxError.java
@@ -19,27 +19,74 @@
 package org.apache.tajo.engine.query.exception;
 
 
+import org.apache.commons.lang.StringUtils;
+
 public class TQLSyntaxError extends InvalidQueryException {
-	private static final long serialVersionUID = 5388279335175632066L;
+  private static final long serialVersionUID = 5388279335175632066L;
 
   private String query;
   private String errorMessage;
   private String detailedMessage;
+  private TQLParseError parseError;
 
-	public TQLSyntaxError(String query, String errorMessage) {
+  public TQLSyntaxError(String query, String errorMessage) {
     this.query = query;
     this.errorMessage = errorMessage;
-	}
+  }
+
+  public TQLSyntaxError(String query, TQLParseError e) {
+    this.query = query;
+    this.errorMessage = e.getMessage();
+    this.parseError = e;
+  }
 
   @Override
   public String getMessage() {
     if (detailedMessage == null) {
-      StringBuilder sb = new StringBuilder();
-      sb.append("ERROR: " + errorMessage).append("\n");
-      sb.append("LINE: " + query);
-      detailedMessage = sb.toString();
+      if (parseError != null) {
+        detailedMessage = getDetailedMessageWithLocation();
+      } else {
+        StringBuilder sb = new StringBuilder();
+        sb.append("ERROR: " + errorMessage).append("\n");
+        sb.append("LINE: " + query);
+        detailedMessage = sb.toString();
+      }
     }
 
     return detailedMessage;
   }
+
+  private String getDetailedMessageWithLocation() {
+    StringBuilder sb = new StringBuilder();
+    int displayLimit = 80;
+    String queryPrefix = "LINE " + parseError.getErrorLine() + ":" +parseError.getErrorPosition()
+ " ";
+    String prefixPadding = StringUtils.repeat(" ", queryPrefix.length());
+    String locationString = StringUtils.repeat(" ", parseError.getErrorPosition()) + "^";
+
+    sb.append("ERROR: " + this.errorMessage).append("\n");
+    sb.append(queryPrefix);
+
+    if (query.length() > displayLimit) {
+      int padding = (displayLimit / 2);
+
+      String ellipsis = " ... ";
+      int startPos = locationString.length() - padding - 1;
+      if (startPos <= 0) {
+        startPos = 0;
+        sb.append(query.substring(startPos, displayLimit)).append(ellipsis).append("\n");
+        sb.append(prefixPadding).append(locationString);
+      } else if (query.length() - (locationString.length() + padding) <= 0) {
+        startPos = query.length() - displayLimit - 1;
+        sb.append(ellipsis).append(query.substring(startPos)).append("\n");
+        sb.append(prefixPadding).append(locationString.substring(startPos - ellipsis.length()));
+      } else {
+        sb.append(ellipsis).append(query.substring(startPos, startPos + displayLimit)).append(ellipsis).append("\n");
+        sb.append(prefixPadding).append(locationString.substring(startPos - ellipsis.length()));
+      }
+    } else {
+      sb.append(query).append("\n");
+      sb.append(prefixPadding).append(locationString);
+    }
+    return sb.toString();
+  }
 }


Mime
View raw message