/** * 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.engine.parser; import org.antlr.v4.runtime.Token; import org.apache.commons.lang.StringUtils; public class SQLParseError extends RuntimeException { private String header; private String errorLine; private int charPositionInLine; private int line; private Token offendingToken; private String detailedMessage; public SQLParseError(Token offendingToken, int line, int charPositionInLine, String msg, String errorLine) { super(msg); this.offendingToken = offendingToken; this.charPositionInLine = charPositionInLine; this.line = line; this.errorLine = errorLine; this.header = msg; } @Override public String getMessage() { if (detailedMessage == null) { if (offendingToken != null) { detailedMessage = getDetailedMessageWithLocation(); } else { StringBuilder sb = new StringBuilder(); sb.append("ERROR: ").append(header).append("\n"); sb.append("LINE: ").append(errorLine); detailedMessage = sb.toString(); } } return detailedMessage; } public String getMessageHeader(){ return this.header; } private String getDetailedMessageWithLocation() { StringBuilder sb = new StringBuilder(); int displayLimit = 80; String queryPrefix = "LINE " + line + ":" + charPositionInLine + " "; String prefixPadding = StringUtils.repeat(" ", queryPrefix.length()); String locationString; int tokenLength = offendingToken.getStopIndex() - offendingToken.getStartIndex() + 1; if(tokenLength > 0){ locationString = StringUtils.repeat(" ", charPositionInLine) + StringUtils.repeat("^", tokenLength); } else { locationString = StringUtils.repeat(" ", charPositionInLine) + "^"; } sb.append("ERROR: ").append(header).append("\n"); sb.append(queryPrefix); if (errorLine.length() > displayLimit) { int padding = (displayLimit / 2); String ellipsis = " ... "; int startPos = locationString.length() - padding - 1; if (startPos <= 0) { startPos = 0; sb.append(errorLine.substring(startPos, displayLimit)).append(ellipsis).append("\n"); sb.append(prefixPadding).append(locationString); } else if (errorLine.length() - (locationString.length() + padding) <= 0) { startPos = errorLine.length() - displayLimit - 1; sb.append(ellipsis).append(errorLine.substring(startPos)).append("\n"); sb.append(prefixPadding).append(StringUtils.repeat(" ", ellipsis.length())) .append(locationString.substring(startPos)); } else { sb.append(ellipsis).append(errorLine.substring(startPos, startPos + displayLimit)).append(ellipsis).append("\n"); sb.append(prefixPadding).append(StringUtils.repeat(" ", ellipsis.length())) .append(locationString.substring(startPos)); } } else { sb.append(errorLine).append("\n"); sb.append(prefixPadding).append(locationString); } return sb.toString(); } }