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:
@@ -32,6 +32,7 @@ import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.dialect.db2.visitor.DB2ParameterizedOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlParameterizedOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor;
|
||||
@@ -158,6 +159,7 @@ public class ParameterizedOutputVisitorUtils {
|
||||
|| parent instanceof SQLColumnDefinition //
|
||||
|| parent instanceof SQLServerTop //
|
||||
|| parent instanceof SQLAssignItem //
|
||||
|| parent instanceof SQLSelectOrderByItem //
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@ public class SQLEvalVisitorUtils {
|
||||
char ch = (char) intValue;
|
||||
x.putAttribute(EVAL_VALUE, Character.toString(ch));
|
||||
}
|
||||
} else if ("CURRENT_USER".equals(methodName)) {
|
||||
} else if ("current_user".equals(methodName)) {
|
||||
x.putAttribute(EVAL_VALUE, "CURRENT_USER");
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -213,6 +213,15 @@ public class JSONWriter {
|
||||
write("\\\\");
|
||||
} else if (c == '\t') {
|
||||
write("\\t");
|
||||
} else if (c < 16) {
|
||||
write("\\u000");
|
||||
write(Integer.toHexString(c));
|
||||
} else if (c < 32) {
|
||||
write("\\u00");
|
||||
write(Integer.toHexString(c));
|
||||
} else if (c >= 0x7f && c <= 0xA0) {
|
||||
write("\\u00");
|
||||
write(Integer.toHexString(c));
|
||||
} else {
|
||||
write(c);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
} else {
|
||||
throw new IllegalStateException("dbType not support : " + dbType + ", url " + dataSource.getUrl());
|
||||
}
|
||||
|
||||
|
||||
provider.setName(dataSource.getName());
|
||||
|
||||
this.inited = true;
|
||||
@@ -364,6 +364,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
setSqlStatAttribute(statement);
|
||||
}
|
||||
return firstResult;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
if (originalContext != null) {
|
||||
WallContext.setContext(originalContext);
|
||||
@@ -385,6 +388,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
setSqlStatAttribute(statement);
|
||||
}
|
||||
return firstResult;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -404,6 +410,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
setSqlStatAttribute(statement);
|
||||
}
|
||||
return firstResult;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -423,6 +432,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
setSqlStatAttribute(statement);
|
||||
}
|
||||
return firstResult;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -443,6 +455,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
}
|
||||
|
||||
return updateCounts;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -455,6 +470,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
try {
|
||||
sql = check(sql);
|
||||
return chain.statement_executeQuery(statement, sql);
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -468,6 +486,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
int updateCount = chain.statement_executeUpdate(statement, sql);
|
||||
statExecuteUpdate(updateCount);
|
||||
return updateCount;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -482,6 +503,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
int updateCount = chain.statement_executeUpdate(statement, sql, autoGeneratedKeys);
|
||||
statExecuteUpdate(updateCount);
|
||||
return updateCount;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -496,6 +520,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
int updateCount = chain.statement_executeUpdate(statement, sql, columnIndexes);
|
||||
statExecuteUpdate(updateCount);
|
||||
return updateCount;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -520,6 +547,9 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
int updateCount = chain.statement_executeUpdate(statement, sql, columnNames);
|
||||
statExecuteUpdate(updateCount);
|
||||
return updateCount;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount();
|
||||
throw ex;
|
||||
} finally {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -527,33 +557,48 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
|
||||
@Override
|
||||
public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException {
|
||||
boolean firstResult = chain.preparedStatement_execute(statement);
|
||||
try {
|
||||
boolean firstResult = chain.preparedStatement_execute(statement);
|
||||
|
||||
if (!firstResult) {
|
||||
WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);
|
||||
int updateCount = statement.getUpdateCount();
|
||||
if (sqlStat != null) {
|
||||
provider.addUpdateCount(sqlStat, updateCount);
|
||||
if (!firstResult) {
|
||||
WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);
|
||||
int updateCount = statement.getUpdateCount();
|
||||
if (sqlStat != null) {
|
||||
provider.addUpdateCount(sqlStat, updateCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstResult;
|
||||
return firstResult;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount(statement);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)
|
||||
throws SQLException {
|
||||
return chain.preparedStatement_executeQuery(statement);
|
||||
try {
|
||||
return chain.preparedStatement_executeQuery(statement);
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount(statement);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int preparedStatement_executeUpdate(FilterChain chain, PreparedStatementProxy statement) throws SQLException {
|
||||
int updateCount = chain.preparedStatement_executeUpdate(statement);
|
||||
WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);
|
||||
if (sqlStat != null) {
|
||||
provider.addUpdateCount(sqlStat, updateCount);
|
||||
try {
|
||||
int updateCount = chain.preparedStatement_executeUpdate(statement);
|
||||
WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);
|
||||
if (sqlStat != null) {
|
||||
provider.addUpdateCount(sqlStat, updateCount);
|
||||
}
|
||||
return updateCount;
|
||||
} catch (SQLException ex) {
|
||||
incrementExecuteErrorCount(statement);
|
||||
throw ex;
|
||||
}
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
public void setSqlStatAttribute(StatementProxy stmt) {
|
||||
@@ -585,6 +630,27 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
provider.addUpdateCount(sqlStat, updateCount);
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementExecuteErrorCount(PreparedStatementProxy statement) {
|
||||
WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);
|
||||
if (sqlStat != null) {
|
||||
sqlStat.incrementAndGetExecuteErrorCount();
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementExecuteErrorCount() {
|
||||
WallContext context = WallContext.current();
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
WallSqlStat sqlStat = context.getSqlStat();
|
||||
if (sqlStat == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
sqlStat.incrementAndGetExecuteErrorCount();
|
||||
}
|
||||
|
||||
public String check(String sql) throws SQLException {
|
||||
WallCheckResult checkResult = provider.check(sql);
|
||||
|
||||
@@ -64,7 +64,7 @@ public abstract class WallProvider {
|
||||
private LRUCache<String, WallSqlStat> blackList;
|
||||
private LRUCache<String, WallSqlStat> blackMergedList;
|
||||
|
||||
private int blackSqlMaxSize = 100; // 1k
|
||||
private int blackSqlMaxSize = 200; // 1k
|
||||
|
||||
protected final WallConfig config;
|
||||
|
||||
|
||||
@@ -25,15 +25,19 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
public class WallSqlStat {
|
||||
|
||||
private volatile long executeCount;
|
||||
private volatile long executeErrorCount;
|
||||
private volatile long fetchRowCount;
|
||||
private volatile long updateCount;
|
||||
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> executeCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"executeCount");
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> fetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"fetchRowCount");
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> updateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"updateCount");
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> executeCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"executeCount");
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> executeErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"executeErrorCount");
|
||||
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> fetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"fetchRowCount");
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> updateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"updateCount");
|
||||
private final Map<String, WallSqlTableStat> tableStats;
|
||||
|
||||
private final List<Violation> violations;
|
||||
@@ -79,12 +83,16 @@ public class WallSqlStat {
|
||||
return executeCountUpdater.incrementAndGet(this);
|
||||
}
|
||||
|
||||
public long incrementAndGetExecuteErrorCount() {
|
||||
return executeErrorCountUpdater.incrementAndGet(this);
|
||||
}
|
||||
|
||||
public long getExecuteCount() {
|
||||
return executeCount;
|
||||
}
|
||||
|
||||
public long incrementAndGetFetchRowCount() {
|
||||
return fetchRowCountUpdater.incrementAndGet(this);
|
||||
public long getExecuteErrorCount() {
|
||||
return executeErrorCount;
|
||||
}
|
||||
|
||||
public long addAndFetchRowCount(long delta) {
|
||||
@@ -123,6 +131,7 @@ public class WallSqlStat {
|
||||
final WallSqlStatValue statValue = new WallSqlStatValue();
|
||||
|
||||
statValue.setExecuteCount(get(this, executeCountUpdater, reset));
|
||||
statValue.setExecuteErrorCount(get(this, executeErrorCountUpdater, reset));
|
||||
statValue.setFetchRowCount(get(this, fetchRowCountUpdater, reset));
|
||||
statValue.setUpdateCount(get(this, updateCountUpdater, reset));
|
||||
statValue.setSyntaxError(this.syntaxError);
|
||||
|
||||
@@ -38,6 +38,9 @@ public class WallSqlStatValue {
|
||||
@MField(aggregate = AggregateType.Sum)
|
||||
private long executeCount;
|
||||
|
||||
@MField(aggregate = AggregateType.Sum)
|
||||
private long executeErrorCount;
|
||||
|
||||
@MField(aggregate = AggregateType.Sum)
|
||||
private long fetchRowCount;
|
||||
|
||||
@@ -118,6 +121,14 @@ public class WallSqlStatValue {
|
||||
this.violationMessage = violationMessage;
|
||||
}
|
||||
|
||||
public long getExecuteErrorCount() {
|
||||
return executeErrorCount;
|
||||
}
|
||||
|
||||
public void setExecuteErrorCount(long executeErrorCount) {
|
||||
this.executeErrorCount = executeErrorCount;
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> sqlStatMap = new LinkedHashMap<String, Object>();
|
||||
sqlStatMap.put("sql", sql);
|
||||
@@ -125,6 +136,10 @@ public class WallSqlStatValue {
|
||||
sqlStatMap.put("sample", sqlSample);
|
||||
}
|
||||
sqlStatMap.put("executeCount", getExecuteCount());
|
||||
|
||||
if (executeErrorCount > 0) {
|
||||
sqlStatMap.put("executeErrorCount", executeErrorCount);
|
||||
}
|
||||
|
||||
if (fetchRowCount > 0) {
|
||||
sqlStatMap.put("fetchRowCount", fetchRowCount);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.alibaba.druid.wall.spi;
|
||||
|
||||
import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -211,6 +213,10 @@ public class WallVisitorUtils {
|
||||
|
||||
SQLExpr where = x.getWhere();
|
||||
if (where != null) {
|
||||
if (queryBlockFromIsNull(visitor, x, false)) {
|
||||
addViolation(visitor, ErrorCode.EmptyQueryHasCondition, "empty select has condition", x);
|
||||
}
|
||||
|
||||
where.setParent(x);
|
||||
checkCondition(visitor, x.getWhere());
|
||||
|
||||
@@ -641,6 +647,10 @@ public class WallVisitorUtils {
|
||||
SQLExpr right = x.getRight();
|
||||
Object leftResult = getValue(visitor, left);
|
||||
Object rightResult = getValue(visitor, right);
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.Like && leftResult instanceof String && leftResult.equals(rightResult)) {
|
||||
addViolation(visitor, ErrorCode.DoubleConstCondition, "same const like", x);
|
||||
}
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.Like || x.getOperator() == SQLBinaryOperator.NotLike) {
|
||||
WallContext context = WallContext.current();
|
||||
@@ -652,8 +662,14 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {
|
||||
if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) {
|
||||
return false;
|
||||
if (rightResult != null && x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr leftBinaryOpExpr = (SQLBinaryOpExpr) x.getLeft();
|
||||
if (leftBinaryOpExpr.getOperator() == SQLBinaryOperator.BooleanAnd) {
|
||||
Object leftRightVal = getValue(leftBinaryOpExpr.getRight());
|
||||
if (leftRightVal != null) {
|
||||
addViolation(visitor, ErrorCode.DoubleConstCondition, "double const condition", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (leftResult == Boolean.TRUE) {
|
||||
@@ -680,6 +696,10 @@ public class WallVisitorUtils {
|
||||
if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String dbType = null;
|
||||
@@ -944,6 +964,10 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
public static Object getValue(WallVisitor visitor, SQLExpr x) {
|
||||
if (x != null && x.getAttributes().containsKey(EVAL_VALUE)) {
|
||||
return x.getAttribute(EVAL_VALUE);
|
||||
}
|
||||
|
||||
if (x instanceof SQLBinaryOpExpr) {
|
||||
return getValue(visitor, (SQLBinaryOpExpr) x);
|
||||
}
|
||||
@@ -978,17 +1002,17 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
if (x instanceof SQLMethodInvokeExpr //
|
||||
|| x instanceof SQLBetweenExpr //
|
||||
|| x instanceof SQLInListExpr //
|
||||
|| x instanceof SQLUnaryExpr //
|
||||
) {
|
||||
|| x instanceof SQLBetweenExpr //
|
||||
|| x instanceof SQLInListExpr //
|
||||
|| x instanceof SQLUnaryExpr //
|
||||
) {
|
||||
String dbType = null;
|
||||
if (visitor != null) {
|
||||
dbType = visitor.getDbType();
|
||||
}
|
||||
return SQLEvalVisitorUtils.eval(dbType, x, Collections.emptyList(), false);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1495,6 +1519,10 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
public static boolean queryBlockFromIsNull(WallVisitor visitor, SQLSelectQuery query) {
|
||||
return queryBlockFromIsNull(visitor, query, true);
|
||||
}
|
||||
|
||||
public static boolean queryBlockFromIsNull(WallVisitor visitor, SQLSelectQuery query, boolean checkSelectConst) {
|
||||
if (query instanceof SQLSelectQueryBlock) {
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;
|
||||
SQLTableSource from = queryBlock.getFrom();
|
||||
@@ -1526,15 +1554,17 @@ public class WallVisitorUtils {
|
||||
}
|
||||
}
|
||||
|
||||
boolean allIsConst = true;
|
||||
for (SQLSelectItem item : queryBlock.getSelectList()) {
|
||||
if (getValue(visitor, item.getExpr()) == null) {
|
||||
allIsConst = false;
|
||||
break;
|
||||
if (checkSelectConst) {
|
||||
boolean allIsConst = true;
|
||||
for (SQLSelectItem item : queryBlock.getSelectList()) {
|
||||
if (getValue(visitor, item.getExpr()) == null) {
|
||||
allIsConst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allIsConst) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (allIsConst) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ public interface ErrorCode {
|
||||
public final static int BITWISE = 2103;
|
||||
public final static int NONE_CONDITION = 2104;
|
||||
public final static int LIKE_NUMBER = 2105;
|
||||
public final static int EmptyQueryHasCondition = 2106;
|
||||
public final static int DoubleConstCondition = 2107;
|
||||
public final static int SameConstLike = 2108;
|
||||
|
||||
public final static int NOT_PARAMETERIZED = 2200;
|
||||
public final static int MULTI_TENANT = 2201;
|
||||
|
||||
@@ -9,4 +9,7 @@ benchmark
|
||||
current_user
|
||||
sleep
|
||||
extractvalue
|
||||
updatexml
|
||||
updatexml
|
||||
xmltype
|
||||
receive_message
|
||||
pg_sleep
|
||||
@@ -17,4 +17,5 @@ pg_postmaster_start_time
|
||||
pg_trigger_depth
|
||||
session_user
|
||||
user
|
||||
version
|
||||
version
|
||||
pg_sleep
|
||||
@@ -132,6 +132,7 @@
|
||||
<th class="td_lable">SQL</th>
|
||||
<th class="td_lable" ><span id="WhiteListSample" class="lang" langKey="Sample">Sample</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="WhiteListExecuteCount" class="lang" langKey="ExecuteCount">ExecuteCount</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="WhiteListExecuteErrorCount" class="lang" langKey="ExecuteErrorCount">ExecuteErrorCount</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="WhiteListFetchRowCount" class="lang" langKey="FetchRowCount">FetchRowCount</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="WhiteListUpdateCount" class="lang" langKey="SQLUpdateCount">UpdateCount</span></th>
|
||||
</tr>
|
||||
@@ -147,6 +148,7 @@
|
||||
<th class="td_lable" style="width: 50px;"><span id="BlackListNumber" class="lang" langKey="TableNumber">TableNumber</span></th>
|
||||
<th class="td_lable">SQL</th>
|
||||
<th class="td_lable" ><span id="BlackListSample" class="lang" langKey="Sample">Sample</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="violationMessage" class="lang" langKey="violationMessage">violationMessage</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="BlackListExecuteCount" class="lang" langKey="ExecuteCount">ExecuteCount</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="BlackListFetchRowCount" class="lang" langKey="FetchRowCount">FetchRowCount</span></th>
|
||||
<th class="td_lable" style="width: 50px;"><span id="BlackListUpdateCount" class="lang" langKey="SQLUpdateCount">UpdateCount</span></th>
|
||||
@@ -250,7 +252,7 @@
|
||||
var white = whiteList[i];
|
||||
html += "<tr>";
|
||||
html += "<td>"+ (i+1) +"</td>";
|
||||
html += "<td>" + white.sql + "</td>";
|
||||
html += '<td style="word-break:break-all">' + white.sql + "</td>";
|
||||
|
||||
if (white.sample === undefined) {
|
||||
html += "<td></td>";
|
||||
@@ -258,12 +260,18 @@
|
||||
html += '<td style="word-break:break-all">'
|
||||
+ white.sample + "</td>";
|
||||
}
|
||||
|
||||
|
||||
if (white.executeCount === undefined) {
|
||||
html += "<td></td>";
|
||||
} else {
|
||||
html += "<td>" + white.executeCount + "</td>";
|
||||
}
|
||||
|
||||
if (white.executeErrorCount === undefined) {
|
||||
html += "<td></td>";
|
||||
} else {
|
||||
html += "<td>" + white.executeErrorCount + "</td>";
|
||||
}
|
||||
|
||||
if (white.fetchRowCount === undefined) {
|
||||
html += "<td></td>";
|
||||
@@ -288,7 +296,7 @@
|
||||
var black = blackList[i];
|
||||
html += "<tr>";
|
||||
html += "<td>"+ (i+1) +"</td>";
|
||||
html += "<td>" + black.sql + "</td>";
|
||||
html += '<td style="word-break:break-all">' + black.sql + "</td>";
|
||||
|
||||
if (black.sample === undefined) {
|
||||
html += "<td></td>";
|
||||
@@ -296,6 +304,12 @@
|
||||
html += '<td style="word-break:break-all">'
|
||||
+ black.sample + "</td>";
|
||||
}
|
||||
|
||||
if (black.violationMessage === undefined) {
|
||||
html += "<td></td>";
|
||||
} else {
|
||||
html += "<td>" + black.violationMessage + "</td>";
|
||||
}
|
||||
|
||||
if (black.executeCount === undefined) {
|
||||
html += "<td></td>";
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest119 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin' AND 5376=3420 AND 'XSDD'='XSDD'";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest120 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin%' AND SLEEP(5) AND '%'=''";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest121 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin%' AND (SELECT 6384 FROM(SELECT COUNT(*),CONCAT(0x3a64686c3a,(SELECT (CASE WHEN (3252 = 3252) THEN 1 ELSE 0 END)),0x3a766f723a,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) AND '%'=''";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest122 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin%' AND 4667=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(115)||CHR(114)||CHR(110)||CHR(58)||(SELECT (CASE WHEN (4667=4667) THEN 1 ELSE 0 END) FROM DUAL)||CHR(58)||CHR(106)||CHR(112)||CHR(122)||CHR(58)||CHR(62))) FROM DUAL) AND '%'=''";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest123 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin'||(SELECT 'tLrl' FROM DUAL WHERE 3240=3240 AND 5014=3795 )||''";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest124 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin' AND 5859=5666 AND 'Cuqo' LIKE 'Cuqo'";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest125 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin' AND 5963=CONVERT(INT,(CHAR(58)+CHAR(108)+CHAR(105)+CHAR(112)+CHAR(58)+(SELECT (CASE WHEN (5963=5963) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(58)+CHAR(117)+CHAR(107)+CHAR(114)+CHAR(58))) AND 'bSho' LIKE 'bSho'";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
public class MySqlWallTest126 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
String sql = "SELECT name, '******' password, createTime from user where name like 'admin'+(SELECT 'NtTK' WHERE 8000=8000 UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL#'";
|
||||
|
||||
Assert.assertFalse(provider.checkValid(sql));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -118,7 +118,11 @@ public class SQLServerWallTest_0 extends TestCase {
|
||||
public void test_true4() throws Exception {
|
||||
WallProvider provider = initWallProvider();
|
||||
{
|
||||
String sql = "SELECT tableid, chnname FROM r_temptable INNER JOIN sys_func_pwr ss ON r_temptable.tableid = ss.mainid INNER JOIN sys_func_pwr sys ON ss.parentid = sys.funcid WHERE (ismaintable = 1) and 1=1 and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 550) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 551) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 391) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 552) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 393) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 396) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 4628) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 4836) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 394) AND (functype = 8) AND (Closed = 0))) and ss.funcid <> 4298 and ss.funcid <> 7441 AND (ss.funcid IN (SELECT DISTINCT funcid FROM sys_func_pwr WHERE (functype = 8) AND (Closed = 0) )) ORDER BY sys.sortflag ,ss.sortflag ";
|
||||
String sql = "SELECT tableid, chnname "//
|
||||
+ "FROM r_temptable "//
|
||||
+ "INNER JOIN sys_func_pwr ss ON r_temptable.tableid = ss.mainid "//
|
||||
+ "INNER JOIN sys_func_pwr sys ON ss.parentid = sys.funcid " //
|
||||
+ "WHERE (ismaintable = 1) and 1=1 and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 550) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 551) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 391) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 552) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 393) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 396) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 4628) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 4836) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 394) AND (functype = 8) AND (Closed = 0))) and ss.funcid <> 4298 and ss.funcid <> 7441 AND (ss.funcid IN (SELECT DISTINCT funcid FROM sys_func_pwr WHERE (functype = 8) AND (Closed = 0) )) ORDER BY sys.sortflag ,ss.sortflag ";
|
||||
Assert.assertTrue(provider.checkValid(sql));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.alibaba.druid.wall.WallUtils;
|
||||
*
|
||||
*/
|
||||
public class WallSelectWhereTest extends TestCase {
|
||||
private String sql = "SELECT F1, F2 WHERE 1 = 1";
|
||||
private String sql = "SELECT F1, F2 from t WHERE 1 = 1";
|
||||
|
||||
public void testMySql() throws Exception {
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(sql));
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.alibaba.druid.wall.WallUtils;
|
||||
*
|
||||
*/
|
||||
public class WallSelectWhereTest0 extends TestCase {
|
||||
private String sql = "SELECT F1, F2 WHERE 1 = 1 OR F1 = ?";
|
||||
private String sql = "SELECT F1, F2 from t WHERE 1 = 1 OR F1 = ?";
|
||||
|
||||
public void testMySql() throws Exception {
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(sql));
|
||||
|
||||
@@ -29,18 +29,18 @@ import com.alibaba.druid.wall.WallUtils;
|
||||
public class WallSelectWhereTest1 extends TestCase {
|
||||
|
||||
public void testMySql_true() throws Exception {
|
||||
Assert.assertTrue(WallUtils.isValidateMySql("SELECT F1, F2 WHERE 1 = 1 OR FID = ?"));
|
||||
Assert.assertTrue(WallUtils.isValidateMySql("SELECT F1, F2 from t WHERE 1 = 1 OR FID = ?"));
|
||||
}
|
||||
|
||||
public void testORACLE_true() throws Exception {
|
||||
Assert.assertTrue(WallUtils.isValidateOracle("SELECT F1, F2 WHERE 1 = 1 OR FID = ?"));
|
||||
Assert.assertTrue(WallUtils.isValidateOracle("SELECT F1, F2 from t WHERE 1 = 1 OR FID = ?"));
|
||||
}
|
||||
|
||||
public void testMySql_false() throws Exception {
|
||||
Assert.assertFalse(WallUtils.isValidateMySql("SELECT F1, F2 WHERE FID = ? OR 1 = 1"));
|
||||
Assert.assertFalse(WallUtils.isValidateMySql("SELECT F1, F2 from t WHERE FID = ? OR 1 = 1"));
|
||||
}
|
||||
|
||||
public void testORACLE_false() throws Exception {
|
||||
Assert.assertFalse(WallUtils.isValidateOracle("SELECT F1, F2 WHERE FID = ? OR 1 = 1"));
|
||||
Assert.assertFalse(WallUtils.isValidateOracle("SELECT F1, F2 from t WHERE FID = ? OR 1 = 1"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.alibaba.druid.wall.WallUtils;
|
||||
*
|
||||
*/
|
||||
public class WallSelectWhereTest2 extends TestCase {
|
||||
private String sql = "SELECT F1, F2 WHERE 1 = 1 AND FID = ?";
|
||||
private String sql = "SELECT F1, F2 from t WHERE 1 = 1 AND FID = ?";
|
||||
|
||||
public void testMySql() throws Exception {
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(sql));
|
||||
|
||||
Reference in New Issue
Block a user