improved sql format output

This commit is contained in:
shaojin.wensj
2015-07-11 14:27:29 +08:00
parent 60b7139911
commit b36374f7bf
26 changed files with 612 additions and 35 deletions
@@ -56,6 +56,8 @@ public class Lexer {
protected Keywords keywods = Keywords.DEFAULT_KEYWORDS;
protected String stringVal;
protected String commentVal;
protected boolean skipComment = true;
@@ -73,9 +75,24 @@ public class Lexer {
protected boolean hasComment = false;
protected boolean endOfComment = false;
protected boolean keepComments = false;
public Lexer(String input){
this(input, null);
}
public Lexer(String input, CommentHandler commentHandler){
this(input, true);
this.commentHandler = commentHandler;
}
public boolean isKeepComments() {
return keepComments;
}
public void setKeepComments(boolean keepComments) {
this.keepComments = keepComments;
}
public CommentHandler getCommentHandler() {
@@ -270,6 +287,7 @@ public class Lexer {
public final void nextToken() {
bufPos = 0;
hasComment = false;
for (;;) {
if (isWhitespace(ch)) {
@@ -759,6 +777,8 @@ public class Lexer {
}
private void scanMultiLineComment() {
Token lastToken = this.token;
scanChar();
scanChar();
mark = pos;
@@ -782,12 +802,25 @@ public class Lexer {
stringVal = subString(mark, bufPos);
token = Token.MULTI_LINE_COMMENT;
hasComment = true;
if (keepComments) {
commentVal = stringVal;
}
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
return;
}
if (!isAllowComment() && !isSafeComment(stringVal)) {
throw new NotAllowCommentException();
}
}
private void scanSingleLineComment() {
Token lastToken = this.token;
scanChar();
scanChar();
mark = pos;
mark = pos - 1;
bufPos = 0;
for (;;) {
@@ -817,6 +850,17 @@ public class Lexer {
stringVal = subString(mark, bufPos);
token = Token.LINE_COMMENT;
hasComment = true;
if (keepComments) {
commentVal = stringVal;
}
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
return;
}
if (!isAllowComment() && !isSafeComment(stringVal)) {
throw new NotAllowCommentException();
}
}
public void scanIdentifier() {
@@ -972,6 +1016,10 @@ public class Lexer {
public final String stringVal() {
return stringVal;
}
public final String commentVal() {
return commentVal;
}
private boolean isOperator(char ch) {
switch (ch) {
@@ -1080,11 +1128,10 @@ public class Lexer {
}
public static interface CommentHandler {
boolean handle(Token lastToken, String comment);
}
public boolean isHasComment() {
public boolean hasComment() {
return hasComment;
}
@@ -1179,6 +1179,10 @@ public class SQLExprParser extends SQLParser {
public SQLExpr andRest(SQLExpr expr) {
for (;;) {
if (lexer.token() == Token.AND || lexer.token() == Token.AMPAMP) {
if (lexer.isKeepComments() && lexer.hasComment()) {
expr.addAfterComment(lexer.commentVal());
}
lexer.nextToken();
SQLExpr rightExp = relational();
@@ -1682,7 +1686,12 @@ public class SQLExprParser extends SQLParser {
item.setValue(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
} else {
item.setValue(expr());
if (lexer.token() == Token.ALL) {
item.setValue(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
} else {
item.setValue(expr());
}
}
return item;
@@ -158,6 +158,12 @@ public class SQLSelectParser extends SQLParser {
return queryRest(select);
}
SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock();
if (lexer.hasComment() && lexer.isKeepComments()) {
queryBlock.addBeforeComment(lexer.commentVal());
}
accept(Token.SELECT);
@@ -165,8 +171,6 @@ public class SQLSelectParser extends SQLParser {
lexer.nextToken();
}
SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock();
if (lexer.token() == Token.DISTINCT) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
lexer.nextToken();
@@ -234,7 +238,15 @@ public class SQLSelectParser extends SQLParser {
if (lexer.token() == Token.WHERE) {
lexer.nextToken();
queryBlock.setWhere(expr());
SQLExpr where = expr();
if (lexer.hasComment() && lexer.isKeepComments() //
&& lexer.token() != Token.INSERT // odps multi-insert
) {
where.addAfterComment(lexer.commentVal());
}
queryBlock.setWhere(where);
}
}
@@ -326,7 +338,13 @@ public class SQLSelectParser extends SQLParser {
parseTableSourceQueryTableExpr(tableReference);
return parseTableSourceRest(tableReference);
SQLTableSource tableSrc = parseTableSourceRest(tableReference);
if (lexer.hasComment() && lexer.isKeepComments()) {
tableSrc.addAfterComment(lexer.commentVal());
}
return tableSrc;
}
private void parseTableSourceQueryTableExpr(SQLExprTableSource tableReference) {
@@ -88,12 +88,16 @@ import com.alibaba.druid.sql.dialect.odps.parser.OdpsSelectParser;
public class SQLStatementParser extends SQLParser {
protected SQLExprParser exprParser;
protected SQLExprParser exprParser;
protected boolean parseCompleteValues = true;
protected int parseValuesSize = 3;
protected boolean parseCompleteValues = true;
protected int parseValuesSize = 3;
protected List<String> comments;
protected CommentCallback commentCallBack = new CommentCallback();
public SQLStatementParser(String sql){
this(sql, null);
}
@@ -101,11 +105,23 @@ public class SQLStatementParser extends SQLParser {
public SQLStatementParser(String sql, String dbType){
this(new SQLExprParser(sql, dbType));
}
public SQLStatementParser(SQLExprParser exprParser){
super(exprParser.getLexer(), exprParser.getDbType());
this.exprParser = exprParser;
}
protected SQLStatementParser(Lexer lexer, String dbType){
super(lexer, dbType);
}
public boolean isKeepComments() {
return lexer.isKeepComments();
}
public void setKeepComments(boolean keepComments) {
this.lexer.setKeepComments(keepComments);
}
public SQLExprParser getExprParser() {
return exprParser;
@@ -122,13 +138,30 @@ public class SQLStatementParser extends SQLParser {
}
public void parseStatementList(List<SQLStatement> statementList, int max) {
List<String> comments = null;
if (this.comments != null) {
comments = this.comments;
this.comments = null;
}
int size_original = statementList.size();
for (;;) {
boolean isFirstStmt = statementList.size() == size_original + 1;
if (isFirstStmt && comments != null && lexer.isKeepComments()) {
SQLStatement firstStmt = statementList.get(size_original);
for (String comment : comments) {
firstStmt.addBeforeComment(comment);
}
comments = null;
}
if (max != -1) {
if (statementList.size() >= max) {
return;
}
}
if (lexer.token() == Token.EOF) {
return;
}
@@ -136,8 +169,15 @@ public class SQLStatementParser extends SQLParser {
return;
}
if (lexer.token() == (Token.SEMI)) {
if (lexer.token() == Token.SEMI) {
size_original = statementList.size();
this.comments = null;
lexer.nextToken();
comments = this.comments;
if (lexer.isKeepComments()) {
SQLStatement stmt = statementList.get(statementList.size() - 1);
stmt.getAttributes().put("format.semi", Boolean.TRUE);
}
continue;
}
@@ -1781,4 +1821,22 @@ public class SQLStatementParser extends SQLParser {
public void setParseValuesSize(int parseValuesSize) {
this.parseValuesSize = parseValuesSize;
}
class CommentCallback implements Lexer.CommentHandler {
@Override
public boolean handle(Token lastToken, String comment) {
addComment(comment);
return true;
}
}
void addComment(String comment) {
if (comments == null) {
comments = new ArrayList<String>();
}
comments.add(comment);
}
}