improved sql parser.

This commit is contained in:
wenshao
2016-10-20 15:59:10 +08:00
parent f66c08fb51
commit cc58cf8be9
9 changed files with 126 additions and 8 deletions
@@ -47,17 +47,14 @@ import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.druid.util.Utils;
public class SQLUtils {
public static FormatOption DEFAULT_FORMAT_OPTION = new FormatOption();
@@ -669,5 +666,30 @@ public class SQLUtils {
return false;
}
public static long hash(String sql, String dbType) {
Lexer lexer = SQLParserUtils.createLexer(sql, dbType);
StringBuilder buf = new StringBuilder(sql.length());
for (;;) {
lexer.nextToken();
Token token = lexer.token();
if (token == Token.EOF) {
break;
}
if (token == Token.ERROR) {
return Utils.murmurhash2_64(sql);
}
if (buf.length() != 0) {
}
}
return buf.hashCode();
}
}
@@ -114,6 +114,7 @@ public class MySqlLexer extends Lexer {
stringVal = subString(mark - 1, bufPos + 1);
token = Token.LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -353,6 +354,7 @@ public class MySqlLexer extends Lexer {
} else {
stringVal = subString(mark, bufPos);
token = Token.MULTI_LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -399,6 +401,7 @@ public class MySqlLexer extends Lexer {
stringVal = subString(mark, bufPos + 1);
token = Token.LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -115,6 +115,7 @@ public class OdpsLexer extends Lexer {
} else {
stringVal = subString(mark, bufPos + 1);
token = Token.MULTI_LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -166,6 +167,7 @@ public class OdpsLexer extends Lexer {
stringVal = subString(mark, ch != EOI ? bufPos : bufPos + 1);
token = Token.LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -232,6 +232,7 @@ public class OracleLexer extends Lexer {
} else {
stringVal = subString(mark, bufPos);
token = Token.MULTI_LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -277,6 +278,7 @@ public class OracleLexer extends Lexer {
stringVal = subString(mark + 1, bufPos);
token = Token.LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -105,6 +105,7 @@ public class SQLServerLexer extends Lexer {
} else {
stringVal = subString(mark, bufPos);
token = Token.MULTI_LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -146,6 +147,7 @@ public class SQLServerLexer extends Lexer {
stringVal = subString(mark + 1, bufPos);
token = Token.LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -61,7 +61,9 @@ public class Lexer {
protected Keywords keywods = Keywords.DEFAULT_KEYWORDS;
protected String stringVal;
protected int commentCount = 0;
protected List<String> comments = new ArrayList<String>(2);
protected boolean skipComment = true;
@@ -95,6 +97,12 @@ public class Lexer {
this(input, true);
this.commentHandler = commentHandler;
}
public Lexer(String input, CommentHandler commentHandler, String dbType){
this(input, true);
this.commentHandler = commentHandler;
this.dbType = dbType;
}
public boolean isKeepComments() {
return keepComments;
@@ -300,7 +308,7 @@ public class Lexer {
public final void nextToken() {
bufPos = 0;
if (comments != null) {
if (comments != null && comments.size() > 0) {
comments = null;
}
@@ -1104,6 +1112,7 @@ public class Lexer {
stringVal = subString(mark, bufPos);
token = Token.MULTI_LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -1153,6 +1162,7 @@ public class Lexer {
stringVal = subString(mark, bufPos);
token = Token.LINE_COMMENT;
commentCount++;
if (keepComments) {
addComment(stringVal);
}
@@ -1445,6 +1455,10 @@ public class Lexer {
public boolean hasComment() {
return comments != null;
}
public int getCommentCount() {
return commentCount;
}
public void skipToEOF() {
pos = text.length();
@@ -16,18 +16,25 @@
package com.alibaba.druid.sql.parser;
import com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser;
import com.alibaba.druid.sql.dialect.db2.parser.DB2Lexer;
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsExprParser;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsLexer;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleLexer;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixExprParser;
import com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixLexer;
import com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixStatementParser;
import com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser;
import com.alibaba.druid.sql.dialect.postgresql.parser.PGLexer;
import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerExprParser;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerLexer;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
import com.alibaba.druid.util.JdbcUtils;
@@ -106,4 +113,38 @@ public class SQLParserUtils {
return new SQLExprParser(sql);
}
public static Lexer createLexer(String sql, String dbType) {
if (JdbcUtils.ORACLE.equals(dbType) || JdbcUtils.ALI_ORACLE.equals(dbType)) {
return new OracleLexer(sql);
}
if (JdbcUtils.MYSQL.equals(dbType) || //
JdbcUtils.MARIADB.equals(dbType) || //
JdbcUtils.H2.equals(dbType)) {
return new MySqlLexer(sql);
}
if (JdbcUtils.POSTGRESQL.equals(dbType)) {
return new PGLexer(sql);
}
if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) {
return new SQLServerLexer(sql);
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2Lexer(sql);
}
if (JdbcUtils.ODPS.equals(dbType)) {
return new OdpsLexer(sql);
}
if (JdbcUtils.PHOENIX.equals(dbType)) {
return new PhoenixLexer(sql);
}
return new Lexer(sql);
}
}
@@ -64,10 +64,15 @@ public class ParameterizedOutputVisitorUtils {
out.append(";\n");
}
SQLStatement stmt = statementList.get(i);
if (stmt.hasBeforeComment()) {
stmt.getBeforeCommentsDirect().clear();
}
stmt.accept(visitor);
}
if (visitor.getReplaceCount() == 0 && !parser.getLexer().hasComment()) {
if (visitor.getReplaceCount() == 0
&& parser.getLexer().getCommentCount() == 0) {
return sql;
}