mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve sql-wall
This commit is contained in:
+175
-176
@@ -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<SQLStatement> 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<SQLStatement> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user