From ad6223c8ce135082f82882ca630e8ce77d304ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Sun, 18 Mar 2012 17:00:11 +0800 Subject: [PATCH] refactor --- .../ast/statement/MySqlDescribeStatement.java | 27 ++++++++++++ .../mysql/parser/MySqlStatementParser.java | 16 +++++++ .../mysql/visitor/MySqlASTVisitor.java | 7 ++- .../mysql/visitor/MySqlASTVisitorAdapter.java | 11 +++++ .../mysql/visitor/MySqlOutputVisitor.java | 13 ++++++ .../mysql/visitor/MySqlSchemaStatVisitor.java | 30 ++++++++----- .../druid/sql/visitor/SchemaStatVisitor.java | 9 ++-- .../bvt/sql/mysql/MySqlDeleteTest_0.java | 44 +++++++++++++++++++ .../bvt/sql/mysql/MySqlDeleteTest_1.java | 44 +++++++++++++++++++ .../bvt/sql/mysql/MySqlDeleteTest_2.java | 44 +++++++++++++++++++ .../bvt/sql/mysql/MySqlDescribteTest.java | 43 ++++++++++++++++++ 11 files changed, 272 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDescribeStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_0.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDescribeStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDescribeStatement.java new file mode 100644 index 0000000000..b32271dda9 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDescribeStatement.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.sql.dialect.mysql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; + +public class MySqlDescribeStatement extends MySqlStatementImpl { + + private static final long serialVersionUID = 1L; + + private SQLName object; + + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, object); + } + visitor.endVisit(this); + } + + public SQLName getObject() { + return object; + } + + public void setObject(SQLName object) { + this.object = object; + } + +} 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 3741ba13a6..7d6fc7b9e6 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 @@ -36,6 +36,7 @@ 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.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropUser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; @@ -345,9 +346,24 @@ public class MySqlStatementParser extends SQLStatementParser { statementList.add(stmt); return true; } + + if (identifierEquals("DESCRIBE")) { + SQLStatement stmt = parseDescribe(); + statementList.add(stmt); + return true; + } return false; } + + public SQLStatement parseDescribe() throws ParserException { + acceptIdentifier("DESCRIBE"); + + MySqlDescribeStatement stmt = new MySqlDescribeStatement(); + stmt.setObject(this.exprParser.name()); + + return stmt; + } public SQLStatement parseShow() throws ParserException { acceptIdentifier("SHOW"); 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 660cfedd93..1be3a98f22 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 @@ -19,15 +19,16 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; -import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; 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.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropUser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; @@ -196,4 +197,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlOutFileExpr x); void endVisit(MySqlOutFileExpr x); + + boolean visit(MySqlDescribeStatement x); + + void endVisit(MySqlDescribeStatement 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 29e66ce230..a086600c89 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 @@ -14,6 +14,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropUser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; @@ -422,4 +423,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements } + @Override + public boolean visit(MySqlDescribeStatement x) { + return true; + } + + @Override + public void endVisit(MySqlDescribeStatement 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 8be785ac4f..86d1225512 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 @@ -44,6 +44,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropUser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; @@ -1363,4 +1364,16 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public void endVisit(MySqlOutFileExpr x) { } + + @Override + public boolean visit(MySqlDescribeStatement x) { + print("DESCRIBE "); + x.getObject().accept(this); + return false; + } + + @Override + public void endVisit(MySqlDescribeStatement 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 6fbf20ca81..51c5bf813f 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 @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropUser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; @@ -63,8 +64,10 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS setMode(x, Mode.Delete); - setAliasMap(); - + accept(x.getFrom()); + accept(x.getUsing()); + x.getTableSource().accept(this); + if (x.getTableSource() instanceof SQLExprTableSource) { SQLName tableName = (SQLName) ((SQLExprTableSource) x.getTableSource()).getExpr(); String ident = tableName.toString(); @@ -72,18 +75,10 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS TableStat stat = this.getTableStat(ident); stat.incrementDeleteCount(); - } else { - MySqlSchemaStatVisitor tableSourceVisitor = new MySqlSchemaStatVisitor(); - tableSourceVisitor.accept(x.getTableSource()); - for (TableStat.Name name : tableSourceVisitor.getTables().keySet()) { - TableStat stat = this.getTableStat(name.getName()); - stat.incrementDeleteCount(); - } - } + } accept(x.getWhere()); - accept(x.getFrom()); - accept(x.getUsing()); + accept(x.getOrderBy()); accept(x.getLimit()); @@ -487,4 +482,15 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlOutFileExpr x) { } + + @Override + public boolean visit(MySqlDescribeStatement x) { + getTableStat(x.getObject().toString()); + return false; + } + + @Override + public void endVisit(MySqlDescribeStatement x) { + + } } 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 8dff34dc8c..6af0022f01 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -723,10 +723,13 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } if (aliasMap != null) { - if (x.getAlias() != null) { - aliasMap.put(x.getAlias(), ident); + String alias = x.getAlias(); + if (alias != null && !aliasMap.containsKey(alias)) { + aliasMap.put(alias, ident); + } + if (!aliasMap.containsKey(ident)) { + aliasMap.put(ident, ident); } - aliasMap.put(ident, ident); } } else { accept(x.getExpr()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_0.java new file mode 100644 index 0000000000..0056453991 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_0.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +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; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlDeleteTest_0 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + 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(2, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t1"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("t1", "id"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_1.java new file mode 100644 index 0000000000..5e28d2ad44 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_1.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +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; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlDeleteTest_1 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + 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(2, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t1"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("t1", "id"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_2.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_2.java new file mode 100644 index 0000000000..4421e3401c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_2.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +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; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlDeleteTest_2 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + 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(2, visitor.getColumns().size()); + Assert.assertEquals(3, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t1"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("t1", "id"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java new file mode 100644 index 0000000000..524168520b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java @@ -0,0 +1,43 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +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; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlDescribteTest extends MysqlTest { + + public void test_0() throws Exception { + String sql = " DESCRIBE City"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + 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(1, 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"))); + } +}