From 7aa2038498627fc5a76aca0f0ffc9495ba3db616 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 14 Jan 2013 20:45:13 +0800 Subject: [PATCH] improve sql parser performance --- .../sql/dialect/mysql/parser/MySqlLexer.java | 15 +++++++++-- .../com/alibaba/druid/sql/parser/Lexer.java | 2 +- .../druid/sql/visitor/SchemaStatVisitor.java | 27 ++++++++++++++++--- .../com/alibaba/druid/stat/TableStat.java | 8 +++--- .../com/alibaba/druid/util/StringUtils.java | 14 ++++++++++ .../benckmark/sql/MySqlPerfMain_select.java | 26 +++++++++--------- 6 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java index 62afff523b..0b70649d41 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java @@ -209,13 +209,24 @@ public class MySqlLexer extends Lexer { { boolean hasSpecial = false; int startIndex = pos + 1; - int endIndex = text.indexOf('\'', startIndex); + int endIndex = -1; //text.indexOf('\'', startIndex); + for (int i = startIndex; i < text.length(); ++i) { + final char ch = text.charAt(i); + if (ch == '\\') { + hasSpecial = true; + } + if (ch == '\'') { + endIndex = i; + break; + } + } + if (endIndex == -1) { throw new ParserException("unclosed str"); } String stringVal = subString(startIndex, endIndex - startIndex); - hasSpecial = stringVal.indexOf('\\') != -1; +// hasSpecial = stringVal.indexOf('\\') != -1; if (!hasSpecial) { this.stringVal = stringVal; diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index f55884dcea..06a2ad4674 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -79,7 +79,7 @@ public class Lexer { return text.charAt(index); } - public String addSymbol() { + public final String addSymbol() { return subString(mark, bufPos); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index bfdbf64c00..0c77bcb481 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -137,9 +137,30 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } private String handleName(String ident) { - ident = ident.replaceAll("\"", ""); - ident = ident.replaceAll("`", ""); - ident = ident.replaceAll(" ", ""); + boolean flag0 = false; + boolean flag1 = false; + boolean flag2 = false; + for (int i = 0; i < ident.length(); ++i) { + final char ch = ident.charAt(i); + if (ch == '\"') { + flag0 = true; + } else if (ch == '`') { + flag1 = true; + } else if (ch == ' ') { + flag2 = true; + } + } + if (flag0) { + ident = ident.replaceAll("\"", ""); + } + + if (flag1) { + ident = ident.replaceAll("`", ""); + } + + if (flag2) { + ident = ident.replaceAll(" ", ""); + } ident = aliasWrap(ident); diff --git a/src/main/java/com/alibaba/druid/stat/TableStat.java b/src/main/java/com/alibaba/druid/stat/TableStat.java index bb4cbd794f..1eab9866ee 100644 --- a/src/main/java/com/alibaba/druid/stat/TableStat.java +++ b/src/main/java/com/alibaba/druid/stat/TableStat.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.alibaba.druid.util.StringUtils; + public class TableStat { int selectCount = 0; @@ -170,7 +172,7 @@ public class TableStat { } public int hashCode() { - return this.name.toLowerCase().hashCode(); + return StringUtils.lowerHashCode(name); } public boolean equals(Object o) { @@ -401,8 +403,8 @@ public class TableStat { } public int hashCode() { - int tableHashCode = table != null ? table.toLowerCase().hashCode() : 0; - int nameHashCode = name != null ? name.toLowerCase().hashCode() : 0; + int tableHashCode = table != null ? StringUtils.lowerHashCode(table) : 0; + int nameHashCode = name != null ? StringUtils.lowerHashCode(name) : 0; return tableHashCode + nameHashCode; } diff --git a/src/main/java/com/alibaba/druid/util/StringUtils.java b/src/main/java/com/alibaba/druid/util/StringUtils.java index f3750190e1..e80081f37c 100644 --- a/src/main/java/com/alibaba/druid/util/StringUtils.java +++ b/src/main/java/com/alibaba/druid/util/StringUtils.java @@ -91,4 +91,18 @@ public class StringUtils { return false; } + + public static int lowerHashCode(String text) { +// return text.toLowerCase().hashCode(); + int h = 0; + for (int i = 0; i < text.length(); ++i) { + char ch = text.charAt(i); + if (ch >= 'A' && ch <= 'Z') { + ch = (char) (ch + 32); + } + + h = 31 * h + ch; + } + return h; + } } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java index 56e2c6dd00..a303c1fac3 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java @@ -20,9 +20,8 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; -import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; import com.alibaba.druid.sql.test.TestUtils; -import com.alibaba.druid.util.IOUtils; public class MySqlPerfMain_select { @@ -30,9 +29,9 @@ public class MySqlPerfMain_select { System.out.println(System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version")); List arguments = ManagementFactory.getRuntimeMXBean().getInputArguments(); System.out.println(arguments); - + String sql = "SELECT ID, NAME, AGE FROM USER WHERE ID = ?"; - + for (int i = 0; i < 10; ++i) { perfMySql(sql); } @@ -57,15 +56,18 @@ public class MySqlPerfMain_select { return millis; } - static String execMySql(String sql) { - StringBuilder out = new StringBuilder(); - MySqlOutputVisitor visitor = new MySqlOutputVisitor(out); + static void execMySql(String sql) { + MySqlStatementParser parser = new MySqlStatementParser(sql); List statementList = parser.parseStatementList(); - // for (SQLStatement statement : statementList) { - // statement.accept(visitor); - // visitor.println(); - // } - return out.toString(); + + // StringBuilder out = new StringBuilder(); + // MySqlOutputVisitor visitor = new MySqlOutputVisitor(out); +// MySqlASTVisitorAdapter visitor = new MySqlASTVisitorAdapter(); +// +// for (SQLStatement statement : statementList) { +// statement.accept(visitor); +// } + // out.toString(); } }