improve sql parser

This commit is contained in:
wenshao
2013-08-04 10:38:05 +08:00
parent c6d0165893
commit 6de2b73fe1
13 changed files with 263 additions and 22 deletions
@@ -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<SQLExprTableSource> tableSources = new ArrayList<SQLExprTableSource>();
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<SQLExprTableSource> getTableSources() {
return tableSources;
}
}
@@ -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);
}
@@ -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<SQLName> names = new ArrayList<SQLName>();
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();
@@ -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);
} //
@@ -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) {
}
} //
@@ -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) {
}
} //
@@ -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) {
}
}
@@ -101,6 +101,7 @@ public class SQLParser {
case DISABLE:
case SEQUENCE:
case USER:
case ANALYZE:
alias = lexer.stringVal();
lexer.nextToken();
return alias;
@@ -203,6 +203,7 @@ public enum Token {
PURGE("PURGE"),
COMPUTE("COMPUTE"),
ANALYZE("ANALYZE"),
// transact-sql
TOP("TOP"),
@@ -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) {
@@ -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);
@@ -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<SQLStatement> 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")));
}
}
@@ -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<SQLStatement> 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")));
}
}