mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user