diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAnalyzeStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAnalyzeStatement.java new file mode 100644 index 0000000000..6eb32c048b --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAnalyzeStatement.java @@ -0,0 +1,43 @@ +package com.alibaba.druid.sql.dialect.mysql.ast.statement; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; + +public class MySqlAnalyzeStatement extends MySqlStatementImpl { + + private boolean noWriteToBinlog = false; + private boolean local = false; + + protected final List tableSources = new ArrayList(); + + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, tableSources); + } + visitor.endVisit(this); + } + + public boolean isNoWriteToBinlog() { + return noWriteToBinlog; + } + + public void setNoWriteToBinlog(boolean noWriteToBinlog) { + this.noWriteToBinlog = noWriteToBinlog; + } + + public boolean isLocal() { + return local; + } + + public void setLocal(boolean local) { + this.local = local; + } + + public List getTableSources() { + return tableSources; + } + +} 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 2109713b4d..0c150a4080 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 @@ -49,6 +49,7 @@ public class MySqlLexer extends Lexer { map.put("BINARY", Token.BINARY); map.put("SHOW", Token.SHOW); map.put("CACHE", Token.CACHE); + map.put("ANALYZE", Token.ANALYZE); DEFAULT_MYSQL_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 5a21f41cc4..e851dba54f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -45,6 +45,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLForeignKeyConstraint; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; @@ -67,6 +68,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableImportTa import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableOption; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAnalyzeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; @@ -491,6 +493,20 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } + public MySqlAnalyzeStatement parseAnalyze() { + accept(Token.ANALYZE); + accept(Token.TABLE); + + MySqlAnalyzeStatement stmt = new MySqlAnalyzeStatement(); + List names = new ArrayList(); + this.exprParser.names(names, stmt); + + for (SQLName name : names) { + stmt.getTableSources().add(new SQLExprTableSource(name)); + } + return stmt; + } + public SQLStatement parseReset() { acceptIdentifier(RESET); @@ -573,6 +589,12 @@ public class MySqlStatementParser extends SQLStatementParser { return true; } + if (lexer.token() == Token.ANALYZE) { + SQLStatement stmt = parseAnalyze(); + statementList.add(stmt); + return true; + } + if (identifierEquals("HELP")) { lexer.nextToken(); MySqlHelpStatement stmt = new MySqlHelpStatement(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 5625529e04..b909b51433 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -40,6 +40,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableImportTa import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableOption; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAnalyzeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; @@ -552,4 +553,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlPartitioningDef.InValues x); void endVisit(MySqlPartitioningDef.InValues x); + + boolean visit(MySqlAnalyzeStatement x); + + void endVisit(MySqlAnalyzeStatement x); } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index b518532e8a..b2a62bad73 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -40,6 +40,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableImportTa import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableOption; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAnalyzeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; @@ -1225,4 +1226,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq public void endVisit(MySqlPartitionByList x) { } + + @Override + public boolean visit(MySqlAnalyzeStatement x) { + return true; + } + + @Override + public void endVisit(MySqlAnalyzeStatement x) { + + } } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index bbde4490d9..e2b57ed5be 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -62,6 +62,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableImportTa import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableOption; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAnalyzeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; @@ -2995,4 +2996,26 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } } + @Override + public boolean visit(MySqlAnalyzeStatement x) { + print("ANALYZE "); + if (x.isNoWriteToBinlog()) { + print("NO_WRITE_TO_BINLOG "); + } + + if (x.isLocal()) { + print("LOCAL "); + } + + print("TABLE "); + + printAndAccept(x.getTableSources(), ", "); + return false; + } + + @Override + public void endVisit(MySqlAnalyzeStatement x) { + + } + } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index 70f970f95d..23fe7c282d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -53,6 +53,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableImportTa import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableOption; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAnalyzeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; @@ -1309,4 +1310,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS } + @Override + public boolean visit(MySqlAnalyzeStatement x) { + return true; + } + + @Override + public void endVisit(MySqlAnalyzeStatement x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index 8cecf0b8ac..eea6fe0b81 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -101,6 +101,7 @@ public class SQLParser { case DISABLE: case SEQUENCE: case USER: + case ANALYZE: alias = lexer.stringVal(); lexer.nextToken(); return alias; diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 9145b2c493..220f2e5aa3 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -203,6 +203,7 @@ public enum Token { PURGE("PURGE"), COMPUTE("COMPUTE"), + ANALYZE("ANALYZE"), // transact-sql TOP("TOP"), 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 6a9107128b..e6c2d3f248 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -899,27 +899,29 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { TableStat stat = getTableStat(ident); Mode mode = getMode(); - switch (mode) { - case Delete: - stat.incrementDeleteCount(); - break; - case Insert: - stat.incrementInsertCount(); - break; - case Update: - stat.incrementUpdateCount(); - break; - case Select: - stat.incrementSelectCount(); - break; - case Merge: - stat.incrementMergeCount(); - break; - case Drop: - stat.incrementDropCount(); - break; - default: - break; + if (mode != null) { + switch (mode) { + case Delete: + stat.incrementDeleteCount(); + break; + case Insert: + stat.incrementInsertCount(); + break; + case Update: + stat.incrementUpdateCount(); + break; + case Select: + stat.incrementSelectCount(); + break; + case Merge: + stat.incrementMergeCount(); + break; + case Drop: + stat.incrementDropCount(); + break; + default: + break; + } } if (aliasMap != null) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java index 7cfc556845..1e49b9d357 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java @@ -188,7 +188,6 @@ public class MySqlASTVisitorAdapterTest extends TestCase { new MySqlAlterTableAddIndex().accept(adapter); new MySqlAlterTableOption().accept(adapter); new MySqlCreateTableStatement().accept(adapter); - new MySqlHelpStatement().accept(adapter); new MySqlCharExpr().accept(adapter); new MySqlAlterTableAddUnique().accept(adapter); new MySqlUnique().accept(adapter); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAnalyzeTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAnalyzeTest_1.java new file mode 100644 index 0000000000..338f46df45 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAnalyzeTest_1.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlAnalyzeTest_1 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "ANALYZE TABLE t1,t2"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ANALYZE TABLE t1, t2", // + output); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(2, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("City"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlHelpTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlHelpTest_0.java new file mode 100644 index 0000000000..9becaffb7f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlHelpTest_0.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlHelpTest_0 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "HELP 'search_string'"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("HELP 'search_string'", // + output); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("City"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +}