From f5cbc85a7a6b7b67afee3eaa8b879f56f0e68143 Mon Sep 17 00:00:00 2001 From: wenshao Date: Fri, 2 Aug 2013 17:52:42 +0800 Subject: [PATCH] improve sql-wall --- .../parser/SQLServerStatementParser.java | 351 +++++++++--------- .../com/alibaba/druid/wall/WallProvider.java | 21 +- .../druid/wall/WallTableStatValue.java | 13 + .../bvt/filter/wall/WallProviderTest.java | 65 +++- 4 files changed, 263 insertions(+), 187 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index 5b39ebb058..ad1d1c143c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -1,176 +1,175 @@ -/* - * 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.sql.dialect.sqlserver.parser; - -import java.util.List; - -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; -import com.alibaba.druid.sql.ast.statement.SQLInsertInto; -import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.ast.statement.SQLTableSource; -import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; -import com.alibaba.druid.sql.parser.Lexer; -import com.alibaba.druid.sql.parser.SQLSelectParser; -import com.alibaba.druid.sql.parser.SQLStatementParser; -import com.alibaba.druid.sql.parser.Token; - -public class SQLServerStatementParser extends SQLStatementParser { - - public SQLServerStatementParser(String sql){ - super(new SQLServerExprParser(sql)); - } - - public SQLSelectParser createSQLSelectParser() { - return new SQLServerSelectParser(this.exprParser); - } - - public SQLServerStatementParser(Lexer lexer){ - super(new SQLServerExprParser(lexer)); - } - - public boolean parseStatementListDialect(List statementList) { - if (lexer.token() == Token.WITH) { - SQLStatement stmt = parseSelect(); - statementList.add(stmt); - return true; - } - - if (identifierEquals("EXEC") || identifierEquals("EXECUTE")) { - lexer.nextToken(); - - SQLServerExecStatement execStmt = new SQLServerExecStatement(); - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - this.exprParser.exprList(execStmt.getParameters(), execStmt); - accept(Token.RPAREN); - } else { - SQLName moduleName = this.exprParser.name(); - execStmt.setModuleName(moduleName); - - this.exprParser.exprList(execStmt.getParameters(), execStmt); - } - statementList.add(execStmt); - return true; - } - - return false; - } - - public SQLStatement parseInsert() { - SQLServerInsertStatement insertStatement = new SQLServerInsertStatement(); - - if (lexer.token() == Token.INSERT) { - accept(Token.INSERT); - } - - parseInsert0(insertStatement); - return insertStatement; - } - - protected void parseInsert0(SQLInsertInto insert, boolean acceptSubQuery) { - SQLServerInsertStatement insertStatement = (SQLServerInsertStatement) insert; - - if (lexer.token() == Token.INTO) { - lexer.nextToken(); - - SQLName tableName = this.exprParser.name(); - insertStatement.setTableName(tableName); - - if (lexer.token() == Token.LITERAL_ALIAS) { - insertStatement.setAlias(as()); - } - - parseInsert0_hinits(insertStatement); - - if (lexer.token() == Token.IDENTIFIER) { - insertStatement.setAlias(lexer.stringVal()); - lexer.nextToken(); - } - } - - if (lexer.token() == (Token.LPAREN)) { - lexer.nextToken(); - this.exprParser.exprList(insertStatement.getColumns()); - accept(Token.RPAREN); - } - - if (lexer.token() == Token.VALUES) { - lexer.nextToken(); - - for (;;) { - accept(Token.LPAREN); - SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); - this.exprParser.exprList(values.getValues(), values); - insertStatement.getValuesList().add(values); - accept(Token.RPAREN); - - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - } else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) { - SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); - insertStatement.setQuery(queryExpr.getSubQuery()); - } - } - - protected SQLServerUpdateStatement createUpdateStatement() { - return new SQLServerUpdateStatement(); - } - - public SQLUpdateStatement parseUpdateStatement() { - SQLServerUpdateStatement udpateStatement = createUpdateStatement(); - - accept(Token.UPDATE); - - SQLServerTop top = this.getExprParser().parseTop(); - if (top != null) { - udpateStatement.setTop(top); - } - - SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); - udpateStatement.setTableSource(tableSource); - - parseUpdateSet(udpateStatement); - - if (lexer.token() == Token.FROM) { - lexer.nextToken(); - SQLTableSource from = this.exprParser.createSelectParser().parseTableSource(); - udpateStatement.setFrom(from); - } - - if (lexer.token() == (Token.WHERE)) { - lexer.nextToken(); - udpateStatement.setWhere(this.exprParser.expr()); - } - - return udpateStatement; - } - - public SQLServerExprParser getExprParser() { - return (SQLServerExprParser) exprParser; - } -} +/* + * 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.sql.dialect.sqlserver.parser; + +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.statement.SQLInsertInto; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLSelectParser; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.parser.Token; + +public class SQLServerStatementParser extends SQLStatementParser { + + public SQLServerStatementParser(String sql){ + super(new SQLServerExprParser(sql)); + } + + public SQLSelectParser createSQLSelectParser() { + return new SQLServerSelectParser(this.exprParser); + } + + public SQLServerStatementParser(Lexer lexer){ + super(new SQLServerExprParser(lexer)); + } + + public boolean parseStatementListDialect(List statementList) { + if (lexer.token() == Token.WITH) { + SQLStatement stmt = parseSelect(); + statementList.add(stmt); + return true; + } + + if (identifierEquals("EXEC") || identifierEquals("EXECUTE")) { + lexer.nextToken(); + + SQLServerExecStatement execStmt = new SQLServerExecStatement(); + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + this.exprParser.exprList(execStmt.getParameters(), execStmt); + accept(Token.RPAREN); + } else { + SQLName moduleName = this.exprParser.name(); + execStmt.setModuleName(moduleName); + + this.exprParser.exprList(execStmt.getParameters(), execStmt); + } + statementList.add(execStmt); + return true; + } + + return false; + } + + public SQLStatement parseInsert() { + SQLServerInsertStatement insertStatement = new SQLServerInsertStatement(); + + if (lexer.token() == Token.INSERT) { + accept(Token.INSERT); + } + + parseInsert0(insertStatement); + return insertStatement; + } + + protected void parseInsert0(SQLInsertInto insert, boolean acceptSubQuery) { + SQLServerInsertStatement insertStatement = (SQLServerInsertStatement) insert; + + if (lexer.token() == Token.INTO) { + lexer.nextToken(); + + SQLName tableName = this.exprParser.name(); + insertStatement.setTableName(tableName); + + if (lexer.token() == Token.LITERAL_ALIAS) { + insertStatement.setAlias(as()); + } + + parseInsert0_hinits(insertStatement); + + if (lexer.token() == Token.IDENTIFIER) { + insertStatement.setAlias(lexer.stringVal()); + lexer.nextToken(); + } + } + + if (lexer.token() == (Token.LPAREN)) { + lexer.nextToken(); + this.exprParser.exprList(insertStatement.getColumns()); + accept(Token.RPAREN); + } + + if (lexer.token() == Token.VALUES) { + lexer.nextToken(); + + for (;;) { + accept(Token.LPAREN); + SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); + this.exprParser.exprList(values.getValues(), values); + insertStatement.getValuesList().add(values); + accept(Token.RPAREN); + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else { + break; + } + } + } else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) { + SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); + insertStatement.setQuery(queryExpr.getSubQuery()); + } + } + + protected SQLServerUpdateStatement createUpdateStatement() { + return new SQLServerUpdateStatement(); + } + + public SQLUpdateStatement parseUpdateStatement() { + SQLServerUpdateStatement udpateStatement = createUpdateStatement(); + + accept(Token.UPDATE); + + SQLServerTop top = this.getExprParser().parseTop(); + if (top != null) { + udpateStatement.setTop(top); + } + + SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); + udpateStatement.setTableSource(tableSource); + + parseUpdateSet(udpateStatement); + + if (lexer.token() == Token.FROM) { + lexer.nextToken(); + SQLTableSource from = this.exprParser.createSelectParser().parseTableSource(); + udpateStatement.setFrom(from); + } + + if (lexer.token() == (Token.WHERE)) { + lexer.nextToken(); + udpateStatement.setWhere(this.exprParser.expr()); + } + + return udpateStatement; + } + + public SQLServerExprParser getExprParser() { + return (SQLServerExprParser) exprParser; + } +} diff --git a/src/main/java/com/alibaba/druid/wall/WallProvider.java b/src/main/java/com/alibaba/druid/wall/WallProvider.java index d130c839fd..87270e87f4 100644 --- a/src/main/java/com/alibaba/druid/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/WallProvider.java @@ -832,8 +832,13 @@ public abstract class WallProvider { WallTableStat tableStat = entry.getValue(); WallTableStatValue tableStatValue = tableStat.getStatValue(reset); + + if (tableStatValue.getTotalExecuteCount() == 0) { + continue; + } + tableStatValue.setName(tableName); - + statValue.getTables().add(tableStatValue); } @@ -842,6 +847,10 @@ public abstract class WallProvider { WallFunctionStat functionStat = entry.getValue(); WallFunctionStatValue functionStatValue = functionStat.getStatValue(reset); + + if (functionStatValue.getInvokeCount() == 0) { + continue; + } functionStatValue.setName(functionName); statValue.getFunctions().add(functionStatValue); @@ -855,6 +864,11 @@ public abstract class WallProvider { String sql = entry.getKey(); WallSqlStat sqlStat = entry.getValue(); WallSqlStatValue sqlStatValue = sqlStat.getStatValue(reset); + + if (sqlStatValue.getExecuteCount() == 0) { + continue; + } + sqlStatValue.setSql(sql); statValue.getWhiteList().add(sqlStatValue); } @@ -865,6 +879,11 @@ public abstract class WallProvider { String sql = entry.getKey(); WallSqlStat sqlStat = entry.getValue(); WallSqlStatValue sqlStatValue = sqlStat.getStatValue(reset); + + if (sqlStatValue.getExecuteCount() == 0) { + continue; + } + sqlStatValue.setSql(sql); statValue.getBlackList().add(sqlStatValue); } diff --git a/src/main/java/com/alibaba/druid/wall/WallTableStatValue.java b/src/main/java/com/alibaba/druid/wall/WallTableStatValue.java index 4e9a9c668e..9237910cab 100644 --- a/src/main/java/com/alibaba/druid/wall/WallTableStatValue.java +++ b/src/main/java/com/alibaba/druid/wall/WallTableStatValue.java @@ -45,6 +45,19 @@ public class WallTableStatValue { this.name = name; } + public long getTotalExecuteCount() { + return selectCount // + + selectIntoCount // + + insertCount // + + updateCount // + + deleteCount // + + truncateCount // + + createCount // + + dropCount // + + replaceCount // + ; + } + public String getName() { return name; } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallProviderTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallProviderTest.java index 87a64cf63a..798082fcba 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallProviderTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallProviderTest.java @@ -4,33 +4,34 @@ import junit.framework.TestCase; import org.junit.Assert; +import com.alibaba.druid.wall.WallProviderStatValue; import com.alibaba.druid.wall.WallSqlStat; import com.alibaba.druid.wall.WallTableStat; import com.alibaba.druid.wall.spi.MySqlWallProvider; - public class WallProviderTest extends TestCase { + public void test_getSqlStat() throws Exception { String whiteSql_1 = "select * from t1 where fid = 1"; String whiteSql_2 = "select * from t1 where fid = 2"; - String blackSql_1 = "select * from t2 where fid = 1 OR 1 = 1"; - String blackSql_2 = "select * from t2 where fid = 2 OR 1 = 1"; - + String blackSql_1 = "select * from t2 where len(fid) = 1 OR 1 = 1"; + String blackSql_2 = "select * from t2 where len(fid) = 2 OR 1 = 1"; + MySqlWallProvider provider = new MySqlWallProvider(); - + Assert.assertTrue(provider.checkValid(whiteSql_1)); Assert.assertTrue(provider.checkValid(whiteSql_2)); Assert.assertEquals(1, provider.getSqlList().size()); - + Assert.assertFalse(provider.checkValid(blackSql_1)); Assert.assertFalse(provider.checkValid(blackSql_2)); Assert.assertEquals(2, provider.getSqlList().size()); - + Assert.assertNotNull(provider.getSqlStat(whiteSql_1)); Assert.assertNotNull(provider.getSqlStat(blackSql_1)); - + Assert.assertSame(provider.getSqlStat(blackSql_1), provider.getSqlStat(blackSql_2)); - + WallSqlStat whiteStat_1 = provider.getSqlStat(whiteSql_1); WallSqlStat whiteStat_2 = provider.getSqlStat(whiteSql_2); Assert.assertSame(whiteStat_1, whiteStat_2); @@ -38,14 +39,58 @@ public class WallProviderTest extends TestCase { WallTableStat wallTableStat = provider.getTableStat("t1"); Assert.assertNotNull(wallTableStat); Assert.assertEquals(3, wallTableStat.getFetchRowCount()); + + Assert.assertTrue(provider.checkValid(whiteSql_1)); + Assert.assertTrue(provider.checkValid(whiteSql_2)); + + Assert.assertFalse(provider.checkValid(blackSql_1)); + Assert.assertFalse(provider.checkValid(blackSql_2)); for (int i = 1000; i < 1000 * 2; ++i) { String sql_x = "select * from t1 where fid = " + i; Assert.assertTrue(provider.checkValid(sql_x)); Assert.assertSame(whiteStat_1, provider.getSqlStat(sql_x)); } - + Assert.assertEquals(500, provider.getWhiteList().size()); Assert.assertEquals(2, provider.getSqlList().size()); + + Assert.assertFalse(provider.checkValid("slelc")); + + { + WallProviderStatValue statValue = provider.getStatValue(true); + Assert.assertNotNull(statValue); + + Assert.assertEquals(2, statValue.getTables().size()); + Assert.assertEquals(1, statValue.getFunctions().size()); + + Assert.assertEquals(1009, statValue.getCheckCount()); + Assert.assertEquals(2, statValue.getBlackListHitCount()); + Assert.assertEquals(1005, statValue.getHardCheckCount()); + Assert.assertEquals(1, statValue.getSyntaxErrorCount()); + Assert.assertEquals(5, statValue.getViolationCount()); + Assert.assertEquals(2, statValue.getWhiteListHitCount()); + + Assert.assertEquals(1, statValue.getWhiteList().size()); + Assert.assertEquals(2, statValue.getBlackList().size()); + } + + { + WallProviderStatValue statValue = provider.getStatValue(true); + Assert.assertNotNull(statValue); + + Assert.assertEquals(0, statValue.getTables().size()); + Assert.assertEquals(0, statValue.getFunctions().size()); + + Assert.assertEquals(0, statValue.getCheckCount()); + Assert.assertEquals(0, statValue.getBlackListHitCount()); + Assert.assertEquals(0, statValue.getHardCheckCount()); + Assert.assertEquals(0, statValue.getSyntaxErrorCount()); + Assert.assertEquals(0, statValue.getViolationCount()); + Assert.assertEquals(0, statValue.getWhiteListHitCount()); + + Assert.assertEquals(0, statValue.getWhiteList().size()); + Assert.assertEquals(0, statValue.getBlackList().size()); + } } }