mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
+26
-10
@@ -21,27 +21,43 @@ import java.util.List;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
|
||||
public class MySqlReplaceStatement extends MySqlStatementImpl {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private boolean lowPriority = false;
|
||||
private boolean delayed = false;
|
||||
private boolean lowPriority = false;
|
||||
private boolean delayed = false;
|
||||
|
||||
private SQLName tableName;
|
||||
private final List<SQLExpr> columns = new ArrayList<SQLExpr>();
|
||||
private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();
|
||||
private SQLQueryExpr query;
|
||||
private SQLExprTableSource tableSource;
|
||||
private final List<SQLExpr> columns = new ArrayList<SQLExpr>();
|
||||
private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();
|
||||
private SQLQueryExpr query;
|
||||
|
||||
public SQLName getTableName() {
|
||||
return tableName;
|
||||
if (tableSource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (SQLName) tableSource.getExpr();
|
||||
}
|
||||
|
||||
public void setTableName(SQLName tableName) {
|
||||
this.tableName = tableName;
|
||||
this.setTableSource(new SQLExprTableSource(tableName));
|
||||
}
|
||||
|
||||
public SQLExprTableSource getTableSource() {
|
||||
return tableSource;
|
||||
}
|
||||
|
||||
public void setTableSource(SQLExprTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
public List<SQLExpr> getColumns() {
|
||||
@@ -79,7 +95,7 @@ public class MySqlReplaceStatement extends MySqlStatementImpl {
|
||||
|
||||
public void accept0(MySqlASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, tableName);
|
||||
acceptChild(visitor, tableSource);
|
||||
acceptChild(visitor, columns);
|
||||
acceptChild(visitor, valuesList);
|
||||
acceptChild(visitor, query);
|
||||
|
||||
@@ -523,6 +523,10 @@ public class MySqlExprParser extends SQLExprParser {
|
||||
return parseColumnRest(column);
|
||||
}
|
||||
|
||||
if (identifierEquals("precision") && column.getDataType().getName().equalsIgnoreCase("double")) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (identifierEquals("PARTITION")) {
|
||||
throw new ParserException("syntax error " + lexer.token() + " " + lexer.stringVal());
|
||||
}
|
||||
@@ -589,7 +593,7 @@ public class MySqlExprParser extends SQLExprParser {
|
||||
accept(Token.EQ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
item.setValue(this.expr());
|
||||
|
||||
item.setTarget(var);
|
||||
|
||||
@@ -642,6 +642,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
boolean full = false;
|
||||
if (lexer.token() == Token.FULL) {
|
||||
lexer.nextToken();
|
||||
full = true;
|
||||
}
|
||||
|
||||
if (identifierEquals("PROCESSLIST")) {
|
||||
@@ -651,7 +652,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
if (identifierEquals("COLUMNS")) {
|
||||
if (identifierEquals("COLUMNS") || identifierEquals("FIELDS")) {
|
||||
lexer.nextToken();
|
||||
|
||||
MySqlShowColumnsStatement stmt = parseShowColumns();
|
||||
|
||||
+2
-2
@@ -422,7 +422,7 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlShowColumnsStatement x) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1283,7 +1283,7 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
|
||||
public boolean visit(MySqlAlterTableImportTablespace x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void endVisit(MySqlAlterTableImportTablespace x) {
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -30,6 +31,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.alibaba.druid.VERSION;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
|
||||
import com.alibaba.druid.support.http.stat.WebAppStatManager;
|
||||
import com.alibaba.druid.support.spring.stat.SpringStatManager;
|
||||
import com.alibaba.druid.util.DruidDataSourceUtils;
|
||||
@@ -186,7 +188,7 @@ public final class DruidStatManagerFacade {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
static Map mergWallStat(Map mapA, Map mapB) {
|
||||
public static Map mergWallStat(Map mapA, Map mapB) {
|
||||
if (mapA.size() == 0) {
|
||||
return mapB;
|
||||
}
|
||||
@@ -195,6 +197,7 @@ public final class DruidStatManagerFacade {
|
||||
return mapA;
|
||||
}
|
||||
|
||||
Map<String, Object> newMap = new LinkedHashMap<String, Object>();
|
||||
for (Object item : mapB.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) item;
|
||||
String key = (String) entry.getKey();
|
||||
@@ -202,16 +205,26 @@ public final class DruidStatManagerFacade {
|
||||
Object valueA = mapA.get(key);
|
||||
|
||||
if (valueA == null) {
|
||||
mapA.put(key, valueB);
|
||||
newMap.put(key, valueB);
|
||||
} else if (valueB == null) {
|
||||
newMap.put(key, valueA);
|
||||
} else {
|
||||
if (valueA instanceof Map && valueB instanceof Map) {
|
||||
Object newValue = mergWallStat((Map)valueA, (Map)valueB);
|
||||
mapA.put(key, newValue);
|
||||
newMap.put(key, newValue);
|
||||
} else if (valueA instanceof Set && valueB instanceof Set) {
|
||||
Set<Object> set = new HashSet<Object>();
|
||||
set.addAll((Set) valueA);
|
||||
set.addAll((Set) valueB);
|
||||
newMap.put(key, set);
|
||||
} else {
|
||||
Object sum = SQLEvalVisitorUtils.add(valueA, valueB);
|
||||
newMap.put(key, sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return newMap;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getSqlStatDataList(Object datasource) {
|
||||
|
||||
@@ -15,22 +15,51 @@
|
||||
*/
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
|
||||
public class WallCheckResult {
|
||||
|
||||
private final List<Violation> violations = new ArrayList<Violation>(2);
|
||||
private final List<SQLStatement> statementList = new ArrayList<SQLStatement>(2);
|
||||
private final List<SQLStatement> statementList;
|
||||
private final Map<String, WallSqlTableStat> tableStats;
|
||||
|
||||
private final List<Violation> violations;
|
||||
|
||||
private final Map<String, WallSqlFunctionStat> functionStats;
|
||||
|
||||
private final boolean syntaxError;
|
||||
|
||||
public WallCheckResult(){
|
||||
|
||||
this(null);
|
||||
}
|
||||
|
||||
public WallCheckResult(Violation violation){
|
||||
this.violations.add(violation);
|
||||
public WallCheckResult(WallSqlStat sqlStat){
|
||||
if (sqlStat != null) {
|
||||
tableStats = sqlStat.getTableStats();
|
||||
violations = sqlStat.getViolations();
|
||||
functionStats = sqlStat.getFunctionStats();
|
||||
statementList = Collections.emptyList();
|
||||
syntaxError = sqlStat.isSyntaxError();
|
||||
} else {
|
||||
tableStats = Collections.emptyMap();
|
||||
violations = Collections.emptyList();
|
||||
functionStats = Collections.emptyMap();
|
||||
statementList = Collections.emptyList();
|
||||
syntaxError = false;
|
||||
}
|
||||
}
|
||||
|
||||
public WallCheckResult(List<Violation> violations, Map<String, WallSqlTableStat> tableStats,
|
||||
Map<String, WallSqlFunctionStat> functionStats, List<SQLStatement> statementList,
|
||||
boolean syntaxError){
|
||||
this.tableStats = tableStats;
|
||||
this.violations = violations;
|
||||
this.functionStats = functionStats;
|
||||
this.statementList = statementList;
|
||||
this.syntaxError = syntaxError;
|
||||
}
|
||||
|
||||
public List<Violation> getViolations() {
|
||||
@@ -41,4 +70,16 @@ public class WallCheckResult {
|
||||
return statementList;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, WallSqlTableStat> getTableStats() {
|
||||
return tableStats;
|
||||
}
|
||||
|
||||
public Map<String, WallSqlFunctionStat> getFunctionStats() {
|
||||
return functionStats;
|
||||
}
|
||||
|
||||
public boolean isSyntaxError() {
|
||||
return syntaxError;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
|
||||
public class WallFunctionStat {
|
||||
@@ -39,4 +41,8 @@ public class WallFunctionStat {
|
||||
return "{\"invokeCount\":" + invokeCount + "}";
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
return Collections.<String, Object>singletonMap("invokeCount", invokeCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ public abstract class WallProvider {
|
||||
|
||||
private int MAX_SQL_LENGTH = 2048; // 1k
|
||||
|
||||
private int whiteSqlMaxSize = 10000; // 1k
|
||||
private int whiteSqlMaxSize = 500; // 1k
|
||||
|
||||
private LRUCache<String, WallSqlStat> blackList;
|
||||
|
||||
private int blackSqlMaxSize = 1000; // 1k
|
||||
private int blackSqlMaxSize = 500; // 1k
|
||||
|
||||
protected final WallConfig config;
|
||||
|
||||
@@ -103,6 +103,10 @@ public abstract class WallProvider {
|
||||
|
||||
public WallTableStat getTableStat(String tableName) {
|
||||
String lowerCaseName = tableName.toLowerCase();
|
||||
if (lowerCaseName.startsWith("`") && lowerCaseName.endsWith("`")) {
|
||||
lowerCaseName = lowerCaseName.substring(1, lowerCaseName.length() - 1);
|
||||
}
|
||||
|
||||
return getTableStatWithLowerName(lowerCaseName);
|
||||
}
|
||||
|
||||
@@ -224,7 +228,7 @@ public abstract class WallProvider {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearBlackList() {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
@@ -371,25 +375,111 @@ public abstract class WallProvider {
|
||||
}
|
||||
|
||||
WallContext.createIfNotExists(this.dbType);
|
||||
WallCheckResult result = new WallCheckResult();
|
||||
|
||||
if (config.isDoPrivilegedAllow() && ispPivileged()) {
|
||||
return result;
|
||||
return new WallCheckResult();
|
||||
}
|
||||
|
||||
// first step, check whiteList
|
||||
boolean mulltiTenant = config.getTenantTablePattern() != null && config.getTenantTablePattern().length() > 0;
|
||||
if (!mulltiTenant) {
|
||||
WallCheckResult checkResult = checkWhiteAndBlackList(sql);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
}
|
||||
}
|
||||
|
||||
hardCheckCount.incrementAndGet();
|
||||
final List<Violation> violations = new ArrayList<Violation>();
|
||||
List<SQLStatement> statementList = new ArrayList<SQLStatement>();
|
||||
boolean syntaxError = false;
|
||||
try {
|
||||
SQLStatementParser parser = createParser(sql);
|
||||
parser.getLexer().setCommentHandler(WallCommentHandler.instance);
|
||||
|
||||
if (!config.isCommentAllow()) {
|
||||
parser.getLexer().setAllowComment(false); // deny comment
|
||||
}
|
||||
|
||||
parser.parseStatementList(statementList);
|
||||
|
||||
final Token lastToken = parser.getLexer().token();
|
||||
if (lastToken != Token.EOF) {
|
||||
violations.add(new IllegalSQLObjectViolation("not terminal sql, token " + lastToken, sql));
|
||||
}
|
||||
} catch (NotAllowCommentException e) {
|
||||
violations.add(new SyntaxErrorViolation(e, sql));
|
||||
incrementCommentDeniedCount();
|
||||
} catch (ParserException e) {
|
||||
syntaxErrrorCount.incrementAndGet();
|
||||
syntaxError = true;
|
||||
if (config.isStrictSyntaxCheck()) {
|
||||
violations.add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
violations.add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
|
||||
if (statementList.size() > 1 && !config.isMultiStatementAllow()) {
|
||||
violations.add(new IllegalSQLObjectViolation("multi-statement not allow", sql));
|
||||
}
|
||||
|
||||
WallVisitor visitor = createWallVisitor();
|
||||
|
||||
if (statementList.size() > 0) {
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
try {
|
||||
stmt.accept(visitor);
|
||||
} catch (ParserException e) {
|
||||
violations.add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
}
|
||||
|
||||
if (visitor.getViolations().size() > 0) {
|
||||
violations.addAll(visitor.getViolations());
|
||||
}
|
||||
|
||||
WallSqlStat sqlStat = null;
|
||||
if (violations.size() > 0) {
|
||||
violationCount.incrementAndGet();
|
||||
|
||||
if (sql.length() < MAX_SQL_LENGTH) {
|
||||
sqlStat = addBlackSql(sql, context.getTableStats(), context.getFunctionStats(), violations, syntaxError);
|
||||
}
|
||||
} else {
|
||||
if (sql.length() < MAX_SQL_LENGTH) {
|
||||
sqlStat = addWhiteSql(sql, context.getTableStats(), context.getFunctionStats(), syntaxError);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, WallSqlTableStat> tableStats = null;
|
||||
Map<String, WallSqlFunctionStat> functionStats = null;
|
||||
if (context != null) {
|
||||
tableStats = context.getTableStats();
|
||||
functionStats = context.getFunctionStats();
|
||||
recordStats(tableStats, functionStats);
|
||||
}
|
||||
|
||||
if (sqlStat != null) {
|
||||
new WallCheckResult(sqlStat);
|
||||
}
|
||||
|
||||
return new WallCheckResult(violations, tableStats, functionStats, statementList, syntaxError);
|
||||
}
|
||||
|
||||
private WallCheckResult checkWhiteAndBlackList(String sql) {
|
||||
{
|
||||
WallSqlStat sqlStat = getWhiteSql(sql);
|
||||
if (sqlStat != null) {
|
||||
whiteListHitCount.incrementAndGet();
|
||||
sqlStat.incrementAndGetExecuteCount();
|
||||
|
||||
|
||||
if (sqlStat.isSyntaxError()) {
|
||||
syntaxErrrorCount.incrementAndGet();
|
||||
}
|
||||
|
||||
recordStats(sqlStat.getTableStats(), sqlStat.getFunctionStats());
|
||||
return result;
|
||||
return new WallCheckResult(sqlStat);
|
||||
}
|
||||
}
|
||||
// check black list
|
||||
@@ -405,80 +495,12 @@ public abstract class WallProvider {
|
||||
|
||||
sqlStat.incrementAndGetExecuteCount();
|
||||
recordStats(sqlStat.getTableStats(), sqlStat.getFunctionStats());
|
||||
List<Violation> blackViolations = sqlStat.getViolations();
|
||||
|
||||
result.getViolations().addAll(blackViolations);
|
||||
return result;
|
||||
return new WallCheckResult(sqlStat);
|
||||
}
|
||||
}
|
||||
|
||||
hardCheckCount.incrementAndGet();
|
||||
boolean syntaxError = false;
|
||||
try {
|
||||
SQLStatementParser parser = createParser(sql);
|
||||
parser.getLexer().setCommentHandler(WallCommentHandler.instance);
|
||||
|
||||
if (!config.isCommentAllow()) {
|
||||
parser.getLexer().setAllowComment(false); // deny comment
|
||||
}
|
||||
|
||||
parser.parseStatementList(result.getStatementList());
|
||||
|
||||
final Token lastToken = parser.getLexer().token();
|
||||
if (lastToken != Token.EOF) {
|
||||
result.getViolations().add(new IllegalSQLObjectViolation("not terminal sql, token " + lastToken, sql));
|
||||
}
|
||||
} catch (NotAllowCommentException e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
incrementCommentDeniedCount();
|
||||
} catch (ParserException e) {
|
||||
syntaxErrrorCount.incrementAndGet();
|
||||
syntaxError = true;
|
||||
if (config.isStrictSyntaxCheck()) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
|
||||
if (result.getViolations().size() == 0 && result.getStatementList().size() > 1
|
||||
&& !config.isMultiStatementAllow()) {
|
||||
result.getViolations().add(new IllegalSQLObjectViolation("multi-statement not allow", sql));
|
||||
}
|
||||
|
||||
WallVisitor visitor = createWallVisitor();
|
||||
|
||||
if (result.getStatementList().size() > 0) {
|
||||
SQLStatement stmt = result.getStatementList().get(0);
|
||||
try {
|
||||
stmt.accept(visitor);
|
||||
} catch (ParserException e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
}
|
||||
|
||||
if (visitor.getViolations().size() > 0) {
|
||||
result.getViolations().addAll(visitor.getViolations());
|
||||
}
|
||||
|
||||
if (result.getViolations().size() > 0) {
|
||||
violationCount.incrementAndGet();
|
||||
|
||||
if (sql.length() < MAX_SQL_LENGTH) {
|
||||
addBlackSql(sql, context.getTableStats(), context.getFunctionStats(), result.getViolations(),
|
||||
syntaxError);
|
||||
}
|
||||
} else {
|
||||
if (sql.length() < MAX_SQL_LENGTH) {
|
||||
addWhiteSql(sql, context.getTableStats(), context.getFunctionStats(), syntaxError);
|
||||
}
|
||||
}
|
||||
|
||||
if (context != null) {
|
||||
recordStats(context.getTableStats(), context.getFunctionStats());
|
||||
}
|
||||
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
void recordStats(Map<String, WallSqlTableStat> tableStats, Map<String, WallSqlFunctionStat> functionStats) {
|
||||
@@ -551,7 +573,7 @@ public abstract class WallProvider {
|
||||
public long getViolationCount() {
|
||||
return violationCount.get();
|
||||
}
|
||||
|
||||
|
||||
public long getHardCheckCount() {
|
||||
return hardCheckCount.get();
|
||||
}
|
||||
@@ -589,6 +611,7 @@ public abstract class WallProvider {
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>();
|
||||
|
||||
info.put("checkCount", this.getCheckCount());
|
||||
info.put("hardCheckCount", this.getHardCheckCount());
|
||||
info.put("violationCount", this.getViolationCount());
|
||||
info.put("blackListHitCount", this.getBlackListHitCount());
|
||||
info.put("blackListSize", this.getBlackList().size());
|
||||
@@ -597,25 +620,21 @@ public abstract class WallProvider {
|
||||
info.put("syntaxErrrorCount", this.getSyntaxErrorCount());
|
||||
|
||||
{
|
||||
List<Map<String, Object>> tables = new ArrayList<Map<String, Object>>();
|
||||
Map<String, Map<String, Object>> tables = new LinkedHashMap<String, Map<String, Object>>();
|
||||
for (Map.Entry<String, WallTableStat> entry : this.tableStats.entrySet()) {
|
||||
Map<String, Object> stat = new LinkedHashMap<String, Object>();
|
||||
stat.put("name", entry.getKey());
|
||||
entry.getValue().toMap(stat);
|
||||
tables.add(stat);
|
||||
tables.put(entry.getKey(), entry.getValue().toMap());
|
||||
}
|
||||
info.put("tables", tables);
|
||||
}
|
||||
{
|
||||
List<Map<String, Object>> functions = new ArrayList<Map<String, Object>>();
|
||||
Map<String, Map<String, Object>> functions = new LinkedHashMap<String, Map<String, Object>>();
|
||||
for (Map.Entry<String, WallFunctionStat> entry : this.functionStats.entrySet()) {
|
||||
Map<String, Object> stat = new HashMap<String, Object>();
|
||||
stat.put("name", entry.getValue());
|
||||
stat.put("invokeCount", entry.getValue().getInvokeCount());
|
||||
functions.add(stat);
|
||||
functions.put(entry.getKey(), entry.getValue().toMap());
|
||||
}
|
||||
info.put("functions", functions);
|
||||
}
|
||||
info.put("whiteList", this.getWhiteList());
|
||||
info.put("blackList", this.getBlackList());
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,8 @@ public class WallSqlFunctionStat {
|
||||
public void incrementInvokeCount() {
|
||||
this.invokeCount++;
|
||||
}
|
||||
|
||||
|
||||
public void addInvokeCount(int value) {
|
||||
this.invokeCount += value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,19 @@ public class WallSqlTableStat {
|
||||
private int createCount;
|
||||
private int alterCount;
|
||||
private int dropCount;
|
||||
private int replaceCount;
|
||||
|
||||
public int getReplaceCount() {
|
||||
return replaceCount;
|
||||
}
|
||||
|
||||
public int incrementReplaceCount() {
|
||||
return replaceCount++;
|
||||
}
|
||||
|
||||
public void addReplaceCount(int value) {
|
||||
this.replaceCount+= value;
|
||||
}
|
||||
|
||||
public int getSelectCount() {
|
||||
return selectCount;
|
||||
@@ -35,6 +48,10 @@ public class WallSqlTableStat {
|
||||
this.selectCount++;
|
||||
}
|
||||
|
||||
public void addSelectCount(int value) {
|
||||
this.selectCount += value;
|
||||
}
|
||||
|
||||
public int getSelectIntoCount() {
|
||||
return selectIntoCount;
|
||||
}
|
||||
@@ -43,6 +60,10 @@ public class WallSqlTableStat {
|
||||
this.selectIntoCount++;
|
||||
}
|
||||
|
||||
public void addSelectIntoCount(int value) {
|
||||
this.selectIntoCount += value;
|
||||
}
|
||||
|
||||
public int getInsertCount() {
|
||||
return insertCount;
|
||||
}
|
||||
@@ -51,6 +72,10 @@ public class WallSqlTableStat {
|
||||
this.insertCount++;
|
||||
}
|
||||
|
||||
public void addInsertCount(int value) {
|
||||
this.insertCount += value;
|
||||
}
|
||||
|
||||
public int getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
@@ -59,6 +84,10 @@ public class WallSqlTableStat {
|
||||
this.updateCount++;
|
||||
}
|
||||
|
||||
public void addUpdateCount(int value) {
|
||||
this.deleteCount += value;
|
||||
}
|
||||
|
||||
public int getDeleteCount() {
|
||||
return deleteCount;
|
||||
}
|
||||
@@ -67,6 +96,10 @@ public class WallSqlTableStat {
|
||||
this.deleteCount++;
|
||||
}
|
||||
|
||||
public void addDeleteCount(int value) {
|
||||
this.deleteCount += value;
|
||||
}
|
||||
|
||||
public int getTruncateCount() {
|
||||
return truncateCount;
|
||||
}
|
||||
@@ -75,6 +108,10 @@ public class WallSqlTableStat {
|
||||
this.truncateCount++;
|
||||
}
|
||||
|
||||
public void addTruncateCount(int value) {
|
||||
this.truncateCount += value;
|
||||
}
|
||||
|
||||
public int getCreateCount() {
|
||||
return createCount;
|
||||
}
|
||||
@@ -83,6 +120,10 @@ public class WallSqlTableStat {
|
||||
this.createCount++;
|
||||
}
|
||||
|
||||
public void addCreateCount(int value) {
|
||||
this.createCount += value;
|
||||
}
|
||||
|
||||
public int getAlterCount() {
|
||||
return alterCount;
|
||||
}
|
||||
@@ -91,6 +132,10 @@ public class WallSqlTableStat {
|
||||
this.alterCount++;
|
||||
}
|
||||
|
||||
public void addAlterCount(int value) {
|
||||
this.alterCount += value;
|
||||
}
|
||||
|
||||
public int getDropCount() {
|
||||
return dropCount;
|
||||
}
|
||||
@@ -99,4 +144,7 @@ public class WallSqlTableStat {
|
||||
this.dropCount++;
|
||||
}
|
||||
|
||||
public void addDropCount(int value) {
|
||||
this.dropCount += value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public class WallTableStat {
|
||||
private volatile long createCount;
|
||||
private volatile long alterCount;
|
||||
private volatile long dropCount;
|
||||
private volatile long replaceCount;
|
||||
|
||||
final static AtomicLongFieldUpdater<WallTableStat> selectCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"selectCount");
|
||||
@@ -51,6 +52,8 @@ public class WallTableStat {
|
||||
"alterCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> dropCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"dropCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> replaceCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"replaceCount");
|
||||
|
||||
public WallTableStat(){
|
||||
|
||||
@@ -91,6 +94,10 @@ public class WallTableStat {
|
||||
public long getDropCount() {
|
||||
return dropCount;
|
||||
}
|
||||
|
||||
public long getReplaceCount() {
|
||||
return replaceCount;
|
||||
}
|
||||
|
||||
public void addSqlTableStat(WallSqlTableStat stat) {
|
||||
{
|
||||
@@ -147,6 +154,12 @@ public class WallTableStat {
|
||||
dropCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getReplaceCount();
|
||||
if (val > 0) {
|
||||
replaceCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -155,7 +168,7 @@ public class WallTableStat {
|
||||
|
||||
return JSONUtils.toJSONString(map);
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
return toMap(map);
|
||||
@@ -186,6 +199,9 @@ public class WallTableStat {
|
||||
if (truncateCount > 0) {
|
||||
map.put("truncateCount", truncateCount);
|
||||
}
|
||||
if (replaceCount > 0) {
|
||||
map.put("replaceCount", replaceCount);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStateme
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
|
||||
@@ -342,4 +343,9 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
public boolean visit(SQLSetStatement x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlReplaceStatement x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -872,6 +872,8 @@ public class WallVisitorUtils {
|
||||
tableStat.incrementDeleteCount();
|
||||
} else if (parent instanceof SQLUpdateStatement) {
|
||||
tableStat.incrementUpdateCount();
|
||||
} else if (parent instanceof MySqlReplaceStatement) {
|
||||
tableStat.incrementReplaceCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class MySqlWallDescribteTest extends TestCase {
|
||||
|
||||
public void test_not_allow() throws Exception {
|
||||
WallConfig config = new WallConfig();
|
||||
config.setVariantCheck(true);
|
||||
config.setDescribeAllow(false);
|
||||
|
||||
Assert.assertFalse(WallUtils.isValidateMySql("describe t", config));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.filter.wall;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.support.json.JSONUtils;
|
||||
import com.alibaba.druid.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
/**
|
||||
* SQLServerWallTest
|
||||
*
|
||||
* @author RaymondXiu
|
||||
* @version 1.0, 2012-3-18
|
||||
* @see
|
||||
*/
|
||||
public class MySqlWallTest35 extends TestCase {
|
||||
|
||||
public void test_true() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
|
||||
Assert.assertTrue(provider.checkValid(//
|
||||
"REPLACE INTO `test2tb` VALUES " + //
|
||||
"('51', '6714105741', '亦美珊不掉正品隐形文胸安全硅胶文胸 小胸聚拢比基尼<span class=H>游泳</span>衣泳装', 'http://img03.taobaocdn.com/bao/uploaded/i3/16011019585534199/T1cnlaXA8bXXXXXXXX_!!0-item_pic.jpg', 'liqiang198163', 'c', '25.00', '20.00', '1000.00', '76', '529', '4.86', '4.91', '4.90', '0.00', '4.80', '2878', '77', '12', '15');")); //
|
||||
|
||||
Assert.assertEquals(1, provider.getTableStat("test2tb").getReplaceCount());
|
||||
System.out.println(JSONUtils.toJSONString(provider.getStatsMap()));
|
||||
}
|
||||
}
|
||||
@@ -22,17 +22,17 @@ public class WallStatTest_WhiteList extends TestCase {
|
||||
public void testMySql() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
|
||||
for (int i = 0; i < 1001; ++i) {
|
||||
for (int i = 0; i < 3001; ++i) {
|
||||
String sql = "select * from t where id = " + i;
|
||||
Assert.assertTrue(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
WallTableStat tableStat = provider.getTableStat("t");
|
||||
Assert.assertEquals(1001, tableStat.getSelectCount());
|
||||
Assert.assertEquals(3001, tableStat.getSelectCount());
|
||||
Assert.assertEquals(0, provider.getBlackListHitCount());
|
||||
Assert.assertEquals(0, provider.getWhiteListHitCount());
|
||||
Assert.assertEquals(1000, provider.getWhiteList().size());
|
||||
Assert.assertEquals(1001, provider.getCheckCount());
|
||||
Assert.assertEquals(500, provider.getWhiteList().size());
|
||||
Assert.assertEquals(3001, provider.getCheckCount());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class WallStatTest_blackList_1 extends TestCase {
|
||||
Assert.assertEquals(0, provider.getBlackListHitCount());
|
||||
Assert.assertEquals(0, provider.getWhiteListHitCount());
|
||||
Assert.assertEquals(0, provider.getWhiteList().size());
|
||||
Assert.assertEquals(1000, provider.getBlackList().size());
|
||||
Assert.assertEquals(500, provider.getBlackList().size());
|
||||
Assert.assertEquals(1001, provider.getCheckCount());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.alibaba.druid.bvt.filter.wall;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.stat.DruidStatManagerFacade;
|
||||
import com.alibaba.druid.support.json.JSONUtils;
|
||||
import com.alibaba.druid.wall.WallContext;
|
||||
import com.alibaba.druid.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class WallStatTest_statMap extends TestCase {
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
|
||||
public void testMySql() throws Exception {
|
||||
WallProvider providerA = new MySqlWallProvider();
|
||||
|
||||
{
|
||||
String sql = "select * from t where len(fname) = 1";
|
||||
Assert.assertTrue(providerA.checkValid(sql));
|
||||
}
|
||||
|
||||
WallProvider providerB = new MySqlWallProvider();
|
||||
{
|
||||
String sql = "select * from t where len(fname) = 2";
|
||||
Assert.assertTrue(providerB.checkValid(sql));
|
||||
}
|
||||
|
||||
Map<String, Object> statMapA = providerA.getStatsMap();
|
||||
Map<String, Object> statMapB = providerB.getStatsMap();
|
||||
|
||||
System.out.println(JSONUtils.toJSONString(statMapA));
|
||||
System.out.println(JSONUtils.toJSONString(statMapB));
|
||||
|
||||
Map<String, Object> statMapMerged = DruidStatManagerFacade.mergWallStat(statMapA, statMapB);
|
||||
System.out.println(JSONUtils.toJSONString(statMapMerged));
|
||||
|
||||
Assert.assertEquals(2L, statMapMerged.get("checkCount"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,6 +64,6 @@ public class ConfigErrorTestMysql extends TestCase {
|
||||
|
||||
Assert.assertEquals(0, LOG.getWarnCount());
|
||||
dataSource.init();
|
||||
Assert.assertEquals(1, LOG.getWarnCount());
|
||||
Assert.assertEquals(0, LOG.getWarnCount());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
*/
|
||||
package com.alibaba.druid.bvt.sql.cobar;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSetStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
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 MySqlCreateTableTest10 extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "create table TACCOUNT (" + //
|
||||
" ID varchar(36) not null," + //
|
||||
" ACCOUNT varchar(100) not null," + //
|
||||
" account_money double precision," + //
|
||||
" NAME varchar(100) not null," + //
|
||||
" TYPE integer," + //
|
||||
" primary key (ID)" + //
|
||||
" )";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);
|
||||
print(statementList);
|
||||
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
|
||||
stmt.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(5, visitor.getColumns().size());
|
||||
Assert.assertEquals(0, visitor.getConditions().size());
|
||||
|
||||
Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("TACCOUNT")));
|
||||
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("TACCOUNT", "ID")));
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("TACCOUNT", "ACCOUNT")));
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("TACCOUNT", "account_money")));
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("TACCOUNT", "NAME")));
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("TACCOUNT", "TYPE")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 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 MySqlShowFieldsTest extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "SHOW FIELDS FROM `schema_migrations`";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> 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(0, visitor.getTables().size());
|
||||
Assert.assertEquals(0, visitor.getColumns().size());
|
||||
Assert.assertEquals(0, visitor.getConditions().size());
|
||||
|
||||
// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t_price")));
|
||||
// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t_basic_store")));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.alibaba.druid.bvt.support.json;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.alibaba.druid.support.json.JSONUtils;
|
||||
import com.alibaba.druid.util.IOUtils;
|
||||
|
||||
public class JSONParserTest3 extends TestCase {
|
||||
public void test_parse() throws Exception {
|
||||
String text = IOUtils.readFromResource("bvt/sonar-sql.json");
|
||||
Map<String, Object> result = (Map<String, Object>)JSONUtils.parse(text);
|
||||
LinkedHashMap wallStats = (LinkedHashMap) result.get("Content");
|
||||
System.out.println(wallStats.get("blackList"));
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user