mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve sqlwall rule
This commit is contained in:
@@ -50,6 +50,9 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
|
||||
}
|
||||
|
||||
public void setTableSource(SQLExprTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
package com.alibaba.druid.sql.ast.statement;
|
||||
|
||||
public enum SQLUnionOperator {
|
||||
UNION("UNION"), UNION_ALL("UNION ALL"), MINUS("MINUS"), INTERSECT("INTERSECT"), DISTINCT("UNION DISTINCT");
|
||||
UNION("UNION"), UNION_ALL("UNION ALL"), MINUS("MINUS"), EXCEPT("EXCEPT"), INTERSECT("INTERSECT"),
|
||||
DISTINCT("UNION DISTINCT");
|
||||
|
||||
public final String name;
|
||||
|
||||
|
||||
+4
-1
@@ -30,11 +30,14 @@ public class MySqlLockTableStatement extends MySqlStatementImpl {
|
||||
}
|
||||
|
||||
public void setTableSource(SQLExprTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
public void setTableSource(SQLName name) {
|
||||
this.tableSource = new SQLExprTableSource(name);
|
||||
setTableSource(new SQLExprTableSource(name));
|
||||
}
|
||||
|
||||
public LockType getLockType() {
|
||||
|
||||
@@ -1380,8 +1380,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
print("USING ");
|
||||
x.getUsing().accept(this);
|
||||
|
||||
print(" ON ");
|
||||
print(" ON (");
|
||||
x.getOn().accept(this);
|
||||
print(") ");
|
||||
|
||||
if (x.getUpdateClause() != null) {
|
||||
println();
|
||||
@@ -3383,7 +3384,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
protected void printCascade() {
|
||||
print(" CASCADE CONSTRAINTS");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLMethodInvokeExpr x) {
|
||||
if ("trim".equalsIgnoreCase(x.getMethodName())) {
|
||||
@@ -3403,7 +3404,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return super.visit(x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,9 @@ public class Keywords {
|
||||
map.put("AND", Token.AND);
|
||||
map.put("ANY", Token.ANY);
|
||||
map.put("AS", Token.AS);
|
||||
|
||||
|
||||
map.put("ENABLE", Token.ENABLE);
|
||||
map.put("DISABLE", Token. DISABLE);
|
||||
map.put("DISABLE", Token.DISABLE);
|
||||
|
||||
map.put("ASC", Token.ASC);
|
||||
map.put("BETWEEN", Token.BETWEEN);
|
||||
@@ -61,6 +61,7 @@ public class Keywords {
|
||||
map.put("DROP", Token.DROP);
|
||||
map.put("ELSE", Token.ELSE);
|
||||
map.put("EXPLAIN", Token.EXPLAIN);
|
||||
map.put("EXCEPT", Token.EXCEPT);
|
||||
|
||||
map.put("END", Token.END);
|
||||
map.put("ESCAPE", Token.ESCAPE);
|
||||
@@ -121,18 +122,18 @@ public class Keywords {
|
||||
map.put("WHEN", Token.WHEN);
|
||||
map.put("WHERE", Token.WHERE);
|
||||
map.put("XOR", Token.XOR);
|
||||
|
||||
|
||||
map.put("OVER", Token.OVER);
|
||||
map.put("TO", Token.TO);
|
||||
map.put("USE", Token.USE);
|
||||
|
||||
|
||||
map.put("REPLACE", Token.REPLACE);
|
||||
|
||||
|
||||
map.put("COMMENT", Token.COMMENT);
|
||||
map.put("COMPUTE", Token.COMPUTE);
|
||||
map.put("WITH", Token.WITH);
|
||||
map.put("GRANT", Token.GRANT);
|
||||
|
||||
|
||||
DEFAULT_KEYWORDS = new Keywords(map);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public class SQLSelectParser extends SQLParser {
|
||||
if (select.getOrderBy() == null) {
|
||||
select.setOrderBy(parseOrderBy());
|
||||
}
|
||||
|
||||
|
||||
if (lexer.token() == Token.HINT) {
|
||||
this.exprParser.parseHints(select.getHints());
|
||||
}
|
||||
@@ -103,6 +103,20 @@ public class SQLSelectParser extends SQLParser {
|
||||
return unionRest(union);
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.EXCEPT) {
|
||||
lexer.nextToken();
|
||||
|
||||
SQLUnionQuery union = new SQLUnionQuery();
|
||||
union.setLeft(selectQuery);
|
||||
|
||||
union.setOperator(SQLUnionOperator.EXCEPT);
|
||||
|
||||
SQLSelectQuery right = this.query();
|
||||
union.setRight(right);
|
||||
|
||||
return union;
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.INTERSECT) {
|
||||
lexer.nextToken();
|
||||
|
||||
@@ -145,7 +159,7 @@ public class SQLSelectParser extends SQLParser {
|
||||
}
|
||||
|
||||
accept(Token.SELECT);
|
||||
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ public enum Token {
|
||||
|
||||
ALL("ALL"),
|
||||
UNION("UNION"),
|
||||
EXCEPT("EXCEPT"),
|
||||
INTERSECT("INTERSECT"),
|
||||
MINUS("MINUS"),
|
||||
INNER("INNER"),
|
||||
|
||||
@@ -25,12 +25,12 @@ public interface SQLEvalVisitor extends SQLASTVisitor {
|
||||
public static final String EVAL_EXPR = "eval.expr";
|
||||
public static final Object EVAL_ERROR = new Object();
|
||||
public static final Object EVAL_VALUE_COUNT = new Object();
|
||||
public static final Object EVAL_VALUE_NULL = new Object();
|
||||
public static final Object EVAL_VALUE_NULL = new Object();
|
||||
|
||||
Function getFunction(String funcName);
|
||||
|
||||
void registerFunction(String funcName, Function function);
|
||||
|
||||
|
||||
void unregisterFunction(String funcName);
|
||||
|
||||
List<Object> getParameters();
|
||||
|
||||
@@ -704,7 +704,8 @@ public class SQLEvalVisitorUtils {
|
||||
|
||||
Object conditionValue = item.getConditionExpr().getAttribute(EVAL_VALUE);
|
||||
|
||||
if (eq(value, conditionValue)) {
|
||||
if ((x.getValueExpr() != null && eq(value, conditionValue))
|
||||
|| (x.getValueExpr() == null && conditionValue instanceof Boolean && (Boolean) conditionValue == Boolean.TRUE)) {
|
||||
item.getValueExpr().accept(visitor);
|
||||
|
||||
if (item.getValueExpr().getAttributes().containsKey(EVAL_VALUE)) {
|
||||
@@ -1051,6 +1052,8 @@ public class SQLEvalVisitorUtils {
|
||||
if (list.size() == 1) {
|
||||
return processValue(list.get(0));
|
||||
}
|
||||
} else if (value instanceof Date) {
|
||||
return ((Date) value).getTime();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -1702,6 +1705,10 @@ public class SQLEvalVisitorUtils {
|
||||
return a;
|
||||
}
|
||||
|
||||
if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {
|
||||
return EVAL_VALUE_NULL;
|
||||
}
|
||||
|
||||
if (a instanceof Date || b instanceof Date) {
|
||||
return SQLEvalVisitor.EVAL_ERROR;
|
||||
}
|
||||
|
||||
@@ -33,13 +33,16 @@ public class WallConfig implements WallConfigMBean {
|
||||
private boolean selectWhereAlwayTrueCheck = true;
|
||||
private boolean selectHavingAlwayTrueCheck = true;
|
||||
private boolean selectUnionCheck = true;
|
||||
private boolean selectMinusCheck = true;
|
||||
private boolean selectExceptCheck = true;
|
||||
private boolean selectIntersectCheck = true;
|
||||
private boolean createTableAllow = true;
|
||||
private boolean dropTableAllow = true;
|
||||
private boolean alterTableAllow = true;
|
||||
|
||||
private boolean conditionAndAlwayTrueAllow = false;
|
||||
private boolean conditionDoubleConstAllow = false;
|
||||
private boolean conditionLikeTrueAllow = false;
|
||||
private boolean conditionLikeTrueAllow = true;
|
||||
|
||||
private boolean selectAllColumnAllow = true;
|
||||
|
||||
@@ -53,8 +56,8 @@ public class WallConfig implements WallConfigMBean {
|
||||
|
||||
private boolean insertAllow = true;
|
||||
private boolean mergeAllow = true;
|
||||
private boolean minusAllow = false;
|
||||
private boolean intersectAllow = false;
|
||||
private boolean minusAllow = true;
|
||||
private boolean intersectAllow = true;
|
||||
private boolean replaceAllow = true;
|
||||
private boolean setAllow = true;
|
||||
private boolean commitAllow = true;
|
||||
@@ -398,6 +401,30 @@ public class WallConfig implements WallConfigMBean {
|
||||
this.selectUnionCheck = selectUnionCheck;
|
||||
}
|
||||
|
||||
public boolean isSelectMinusCheck() {
|
||||
return selectMinusCheck;
|
||||
}
|
||||
|
||||
public void setSelectMinusCheck(boolean selectMinusCheck) {
|
||||
this.selectMinusCheck = selectMinusCheck;
|
||||
}
|
||||
|
||||
public boolean isSelectExceptCheck() {
|
||||
return selectExceptCheck;
|
||||
}
|
||||
|
||||
public void setSelectExceptCheck(boolean selectExceptCheck) {
|
||||
this.selectExceptCheck = selectExceptCheck;
|
||||
}
|
||||
|
||||
public boolean isSelectIntersectCheck() {
|
||||
return selectIntersectCheck;
|
||||
}
|
||||
|
||||
public void setSelectIntersectCheck(boolean selectIntersectCheck) {
|
||||
this.selectIntersectCheck = selectIntersectCheck;
|
||||
}
|
||||
|
||||
public boolean isSelectWhereAlwayTrueCheck() {
|
||||
return selectWhereAlwayTrueCheck;
|
||||
}
|
||||
|
||||
@@ -118,8 +118,7 @@ public class DB2WallVisitor extends DB2ASTVisitorAdapter implements WallVisitor
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
return WallVisitorUtils.check(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -121,8 +121,7 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
return WallVisitorUtils.check(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,7 +70,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
this.config = provider.getConfig();
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.ORACLE;
|
||||
@@ -127,8 +127,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
return WallVisitorUtils.check(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,7 +210,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLSelectStatement x) {
|
||||
WallVisitorUtils.clearWallTopStatementContext();
|
||||
@@ -274,7 +273,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
WallVisitorUtils.checkDelete(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void endVisit(OracleDeleteStatement x) {
|
||||
endVisit((SQLDeleteStatement) x);
|
||||
@@ -343,7 +342,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
public boolean visit(SQLCallStatement x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCreateTriggerStatement x) {
|
||||
return false;
|
||||
|
||||
@@ -62,7 +62,7 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor {
|
||||
this.config = provider.getConfig();
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.POSTGRESQL;
|
||||
@@ -119,8 +119,7 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
return WallVisitorUtils.check(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -67,7 +67,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
this.config = provider.getConfig();
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.SQL_SERVER;
|
||||
@@ -138,8 +138,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
return WallVisitorUtils.check(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,6 +152,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLServerExecStatement x) {
|
||||
return false;
|
||||
@@ -278,17 +278,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLServerObjectReferenceExpr x) {
|
||||
if (x.getSchema() != null && !provider.checkDenySchema(x.getSchema())) {
|
||||
this.getViolations().add(new IllegalSQLObjectViolation(ErrorCode.SCHEMA_DENY, "schema not allow : "
|
||||
+ x.getSchema(),
|
||||
this.toSQL(x)));
|
||||
}
|
||||
if (x.getDatabase() != null && !provider.checkDenySchema(x.getDatabase())) {
|
||||
this.getViolations().add(new IllegalSQLObjectViolation(ErrorCode.SCHEMA_DENY, "schema not allow : "
|
||||
+ x.getDatabase(),
|
||||
this.toSQL(x)));
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.SQLStatementImpl;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
|
||||
@@ -41,6 +42,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCaseExpr.Item;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLExistsExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;
|
||||
@@ -126,7 +128,16 @@ public class WallVisitorUtils {
|
||||
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLBinaryOpExpr x) {
|
||||
public static boolean check(WallVisitor visitor, SQLBinaryOpExpr x) {
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanOr || x.getOperator() == SQLBinaryOperator.BooleanAnd) {
|
||||
List<SQLExpr> groupList = SQLUtils.split(x);
|
||||
for (SQLExpr item : groupList) {
|
||||
item.accept(visitor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.Add || x.getOperator() == SQLBinaryOperator.Concat) {
|
||||
List<SQLExpr> groupList = SQLUtils.split(x);
|
||||
if (groupList.size() >= 4) {
|
||||
@@ -148,6 +159,8 @@ public class WallVisitorUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLCreateTableStatement x) {
|
||||
@@ -600,7 +613,7 @@ public class WallVisitorUtils {
|
||||
Boolean booleanVal = SQLEvalVisitorUtils.castToBoolean(result);
|
||||
if (Boolean.TRUE == booleanVal) {
|
||||
final WallConditionContext wallContext = WallVisitorUtils.getWallConditionContext();
|
||||
if (wallContext != null && i != 0) {
|
||||
if (wallContext != null && !isFirst(item)) {
|
||||
wallContext.setPartAlwayTrue(true);
|
||||
}
|
||||
return true;
|
||||
@@ -618,6 +631,47 @@ public class WallVisitorUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {
|
||||
|
||||
List<SQLExpr> groupList = SQLUtils.split(x);
|
||||
|
||||
int dalConst = 0;
|
||||
Boolean allTrue = Boolean.TRUE;
|
||||
for (int i = groupList.size() - 1; i >= 0; --i) {
|
||||
|
||||
SQLExpr item = groupList.get(i);
|
||||
Object result = getValue(visitor, item);
|
||||
Boolean booleanVal = SQLEvalVisitorUtils.castToBoolean(result);
|
||||
|
||||
if (Boolean.TRUE == booleanVal) {
|
||||
final WallConditionContext wallContext = WallVisitorUtils.getWallConditionContext();
|
||||
if (wallContext != null && !isFirst(item)) {
|
||||
wallContext.setPartAlwayTrue(true);
|
||||
}
|
||||
dalConst++;
|
||||
} else if (Boolean.FALSE == booleanVal) {
|
||||
allTrue = Boolean.FALSE;
|
||||
dalConst++;
|
||||
} else {
|
||||
if (allTrue != Boolean.FALSE) {
|
||||
allTrue = null;
|
||||
}
|
||||
dalConst = 0;
|
||||
}
|
||||
|
||||
if (dalConst == 2 && visitor != null && !visitor.getConfig().isConditionDoubleConstAllow()) {
|
||||
addViolation(visitor, ErrorCode.DOUBLE_CONST_CONDITION, "double const condition", x);
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean.TRUE == allTrue) {
|
||||
return true;
|
||||
} else if (Boolean.FALSE == allTrue) {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
SQLExpr left = x.getLeft();
|
||||
SQLExpr right = x.getRight();
|
||||
Object leftResult = getValue(visitor, left);
|
||||
@@ -636,58 +690,6 @@ public class WallVisitorUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {
|
||||
if (visitor != null && !visitor.getConfig().isConditionDoubleConstAllow()) {
|
||||
if (rightResult != null && x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr leftBinaryOpExpr = (SQLBinaryOpExpr) x.getLeft();
|
||||
|
||||
if (leftBinaryOpExpr.getOperator() != SQLBinaryOperator.BooleanAnd //
|
||||
&& leftBinaryOpExpr.getOperator() != SQLBinaryOperator.BooleanOr //
|
||||
&& leftResult != null //
|
||||
&& visitor != null) {
|
||||
addViolation(visitor, ErrorCode.DOUBLE_CONST_CONDITION, "double const condition", x);
|
||||
}
|
||||
|
||||
if (leftBinaryOpExpr.getOperator() == SQLBinaryOperator.BooleanAnd //
|
||||
|| leftBinaryOpExpr.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
Object leftRightVal = getValue(leftBinaryOpExpr.getRight());
|
||||
if (leftRightVal != null) {
|
||||
addViolation(visitor, ErrorCode.DOUBLE_CONST_CONDITION, "double const condition", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (leftResult == Boolean.TRUE) {
|
||||
if (!isFirst(x.getLeft())) {
|
||||
final WallConditionContext current = wallConditionContextLocal.get();
|
||||
if (current != null) {
|
||||
current.setPartAlwayTrue(true);
|
||||
}
|
||||
}
|
||||
} else if (rightResult == Boolean.TRUE) {
|
||||
final WallConditionContext current = wallConditionContextLocal.get();
|
||||
|
||||
boolean isLikeAlwayTrue = false;
|
||||
if (right instanceof SQLBinaryOpExpr
|
||||
&& ((SQLBinaryOpExpr) right).getOperator() == SQLBinaryOperator.Like) {
|
||||
isLikeAlwayTrue = true;
|
||||
}
|
||||
|
||||
if (current != null && !isLikeAlwayTrue) {
|
||||
current.setPartAlwayTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String dbType = null;
|
||||
WallContext wallContext = WallContext.current();
|
||||
if (wallContext != null) {
|
||||
@@ -711,39 +713,58 @@ public class WallVisitorUtils {
|
||||
|
||||
public static List<SQLExpr> getParts(SQLExpr x) {
|
||||
List<SQLExpr> exprs = new ArrayList<SQLExpr>();
|
||||
exprs.add(x);
|
||||
|
||||
if (x instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binary = (SQLBinaryOpExpr) x;
|
||||
if (binary.getOperator() == SQLBinaryOperator.BooleanAnd
|
||||
|| binary.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
exprs.addAll(getParts(((SQLBinaryOpExpr) x).getLeft()));
|
||||
exprs.addAll(getParts(((SQLBinaryOpExpr) x).getRight()));
|
||||
return exprs;
|
||||
while (true) {
|
||||
List<SQLExpr> tmp = partExpr(exprs);
|
||||
|
||||
if (tmp.size() == exprs.size()) {
|
||||
break;
|
||||
}
|
||||
exprs = tmp;
|
||||
}
|
||||
|
||||
exprs.add(x);
|
||||
return exprs;
|
||||
}
|
||||
|
||||
public static List<SQLExpr> partExpr(List<SQLExpr> exprs) {
|
||||
List<SQLExpr> partList = new ArrayList<SQLExpr>();
|
||||
|
||||
for (SQLExpr x : exprs) {
|
||||
if (x instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binary = (SQLBinaryOpExpr) x;
|
||||
if (binary.getOperator() == SQLBinaryOperator.BooleanAnd
|
||||
|| binary.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
partList.add(((SQLBinaryOpExpr) x).getLeft());
|
||||
partList.add(((SQLBinaryOpExpr) x).getRight());
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
partList.add(x);
|
||||
}
|
||||
return partList;
|
||||
}
|
||||
|
||||
public static boolean isFirst(SQLObject x) {
|
||||
if (x == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SQLObject parent = x.getParent();
|
||||
if (!(parent instanceof SQLExpr)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parent instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) parent;
|
||||
if (isFirst(binaryExpr) && x == binaryExpr.getLeft()) {
|
||||
for (;;) {
|
||||
SQLObject parent = x.getParent();
|
||||
if (!(parent instanceof SQLExpr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if (parent instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) parent;
|
||||
if (x == binaryExpr.getRight()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
x = parent;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasWhere(SQLSelectQuery selectQuery) {
|
||||
@@ -993,9 +1014,33 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
if (x instanceof SQLQueryExpr) {
|
||||
|
||||
if (isSimpleCountTableSource(visitor, ((SQLQueryExpr) x).getSubQuery())) {
|
||||
return Integer.valueOf(1);
|
||||
}
|
||||
|
||||
if (isSimpleCaseTableSource(visitor, ((SQLQueryExpr) x).getSubQuery())) {
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) ((SQLQueryExpr) x).getSubQuery().getQuery();
|
||||
SQLCaseExpr caseExpr = (SQLCaseExpr) queryBlock.getSelectList().get(0).getExpr();
|
||||
|
||||
Object result = getValue(caseExpr);
|
||||
|
||||
if (visitor != null && !visitor.getConfig().isCaseConditionAllow()) {
|
||||
boolean leftIsName = false;
|
||||
if (x.getParent() instanceof SQLBinaryOpExpr) {
|
||||
SQLExpr left = ((SQLBinaryOpExpr) x.getParent()).getLeft();
|
||||
if (left instanceof SQLName) {
|
||||
leftIsName = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!leftIsName && result != null) {
|
||||
addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, "const case condition", caseExpr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
String dbType = null;
|
||||
@@ -1011,23 +1056,26 @@ public class WallVisitorUtils {
|
||||
return eval(visitor, dbType, x, Collections.emptyList());
|
||||
}
|
||||
|
||||
if (visitor != null && (!visitor.getConfig().isCaseConditionAllow()) && x instanceof SQLCaseExpr) {
|
||||
SQLCaseExpr caseExpr = (SQLCaseExpr) x;
|
||||
if (x instanceof SQLCaseExpr) {
|
||||
|
||||
boolean leftIsName = false;
|
||||
if (caseExpr.getParent() instanceof SQLBinaryOpExpr) {
|
||||
SQLExpr left = ((SQLBinaryOpExpr) caseExpr.getParent()).getLeft();
|
||||
if (left instanceof SQLName) {
|
||||
leftIsName = true;
|
||||
if (visitor != null && !visitor.getConfig().isCaseConditionAllow()) {
|
||||
SQLCaseExpr caseExpr = (SQLCaseExpr) x;
|
||||
|
||||
boolean leftIsName = false;
|
||||
if (caseExpr.getParent() instanceof SQLBinaryOpExpr) {
|
||||
SQLExpr left = ((SQLBinaryOpExpr) caseExpr.getParent()).getLeft();
|
||||
if (left instanceof SQLName) {
|
||||
leftIsName = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!leftIsName) && caseExpr.getItems().size() > 0) {
|
||||
SQLCaseExpr.Item item = caseExpr.getItems().get(0);
|
||||
Object conditionVal = getValue(visitor, item.getConditionExpr());
|
||||
Object itemVal = getValue(visitor, item.getValueExpr());
|
||||
if (conditionVal instanceof Boolean && itemVal != null) {
|
||||
addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, "const case condition", caseExpr);
|
||||
if (!leftIsName && caseExpr.getValueExpr() == null && caseExpr.getItems().size() > 0) {
|
||||
SQLCaseExpr.Item item = caseExpr.getItems().get(0);
|
||||
Object conditionVal = getValue(visitor, item.getConditionExpr());
|
||||
Object itemVal = getValue(visitor, item.getValueExpr());
|
||||
if (conditionVal instanceof Boolean && itemVal != null) {
|
||||
addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, "const case condition", caseExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1095,6 +1143,40 @@ public class WallVisitorUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isSimpleCaseTableSource(WallVisitor visitor, SQLSelect select) {
|
||||
SQLSelectQuery query = select.getQuery();
|
||||
|
||||
if (query instanceof SQLSelectQueryBlock) {
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;
|
||||
|
||||
boolean allawTrueWhere = false;
|
||||
|
||||
if (queryBlock.getWhere() == null) {
|
||||
allawTrueWhere = true;
|
||||
} else {
|
||||
Object whereValue = getValue(visitor, queryBlock.getWhere());
|
||||
if (whereValue == Boolean.TRUE) {
|
||||
allawTrueWhere = true;
|
||||
} else if (whereValue == Boolean.FALSE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
boolean simpleCase = false;
|
||||
if (queryBlock.getSelectList().size() == 1) {
|
||||
SQLExpr selectItemExpr = queryBlock.getSelectList().get(0).getExpr();
|
||||
if (selectItemExpr instanceof SQLCaseExpr) {
|
||||
simpleCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (allawTrueWhere && simpleCase) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void checkFunctionInTableSource(WallVisitor visitor, SQLMethodInvokeExpr x) {
|
||||
final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get();
|
||||
if (topStatementContext != null && (topStatementContext.fromSysSchema || topStatementContext.fromSysTable)) {
|
||||
@@ -1105,7 +1187,7 @@ public class WallVisitorUtils {
|
||||
|
||||
String methodName = x.getMethodName().toLowerCase();
|
||||
if (!visitor.getProvider().checkDenyTable(methodName)) {
|
||||
if (isTopUpdateStatement(x) || isFirstSelectTableSource(x)) {
|
||||
if (isTopStatementWithTableSource(x) || isFirstSelectTableSource(x)) {
|
||||
if (topStatementContext != null) {
|
||||
topStatementContext.setFromSysSchema(Boolean.TRUE);
|
||||
clearViolation(visitor);
|
||||
@@ -1226,7 +1308,7 @@ public class WallVisitorUtils {
|
||||
owner = WallVisitorUtils.form(owner);
|
||||
if (isInTableSource(x) && !visitor.getProvider().checkDenySchema(owner)) {
|
||||
|
||||
if (!isTopUpdateStatement(x) && !isFirstSelectTableSource(x) && !isFirstInSubQuery(x)) {
|
||||
if (!isTopStatementWithTableSource(x) && !isFirstSelectTableSource(x) && !isFirstInSubQuery(x)) {
|
||||
SQLObject parent = x.getParent();
|
||||
while (parent != null && !(parent instanceof SQLStatement)) {
|
||||
parent = parent.getParent();
|
||||
@@ -1402,7 +1484,8 @@ public class WallVisitorUtils {
|
||||
if (union.getRight() == x && hasTableSource(union.getLeft())) {
|
||||
return false;
|
||||
}
|
||||
} else if (parent instanceof SQLQueryExpr || parent instanceof SQLInSubQueryExpr) {
|
||||
} else if (parent instanceof SQLQueryExpr || parent instanceof SQLInSubQueryExpr
|
||||
|| parent instanceof SQLExistsExpr) {
|
||||
isWhereQueryExpr = isWhereOrHaving(parent);
|
||||
} else if (isWhereQueryExpr && parent instanceof SQLSelectQueryBlock) {
|
||||
if (hasTableSource((SQLSelectQueryBlock) parent)) {
|
||||
@@ -1452,7 +1535,7 @@ public class WallVisitorUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isTopUpdateStatement(SQLObject x) {
|
||||
private static boolean isTopStatementWithTableSource(SQLObject x) {
|
||||
|
||||
for (;;) {
|
||||
if (x instanceof SQLExpr) {
|
||||
@@ -1465,7 +1548,7 @@ public class WallVisitorUtils {
|
||||
if (x instanceof SQLExprTableSource) {
|
||||
x = x.getParent();
|
||||
|
||||
if (x instanceof SQLUpdateStatement) {
|
||||
if (x instanceof SQLStatementImpl) {
|
||||
x = x.getParent();
|
||||
if (x == null) {
|
||||
return true;
|
||||
@@ -1559,7 +1642,7 @@ public class WallVisitorUtils {
|
||||
if (visitor.isDenyTable(tableName)
|
||||
&& !(topStatementContext != null && topStatementContext.fromPermitTable())) {
|
||||
|
||||
if (isTopUpdateStatement(x) || isFirstSelectTableSource(x)) {
|
||||
if (isTopStatementWithTableSource(x) || isFirstSelectTableSource(x)) {
|
||||
if (topStatementContext != null) {
|
||||
topStatementContext.setFromSysTable(Boolean.TRUE);
|
||||
clearViolation(visitor);
|
||||
@@ -1598,6 +1681,7 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
public static void checkUnion(WallVisitor visitor, SQLUnionQuery x) {
|
||||
|
||||
if (x.getOperator() == SQLUnionOperator.MINUS && !visitor.getConfig().isMinusAllow()) {
|
||||
addViolation(visitor, ErrorCode.INTERSET_NOT_ALLOW, "minus not allow", x);
|
||||
return;
|
||||
@@ -1610,6 +1694,7 @@ public class WallVisitorUtils {
|
||||
|
||||
if (WallVisitorUtils.queryBlockFromIsNull(visitor, x.getRight())) {
|
||||
boolean isTopUpdateStatement = false;
|
||||
boolean isTopInsertStatement = false;
|
||||
SQLObject selectParent = x.getParent();
|
||||
while (selectParent instanceof SQLUnionQuery //
|
||||
|| selectParent instanceof SQLJoinTableSource //
|
||||
@@ -1622,7 +1707,11 @@ public class WallVisitorUtils {
|
||||
isTopUpdateStatement = true;
|
||||
}
|
||||
|
||||
if (isTopUpdateStatement) {
|
||||
if (selectParent instanceof SQLInsertStatement) {
|
||||
isTopInsertStatement = true;
|
||||
}
|
||||
|
||||
if (isTopUpdateStatement || isTopInsertStatement) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1631,8 +1720,12 @@ public class WallVisitorUtils {
|
||||
context.incrementUnionWarnnings();
|
||||
}
|
||||
|
||||
if (visitor.getConfig().isSelectUnionCheck()) {
|
||||
addViolation(visitor, ErrorCode.UNION, "union query not contains 'from clause'", x);
|
||||
if (((x.getOperator() == SQLUnionOperator.UNION || x.getOperator() == SQLUnionOperator.UNION_ALL || x.getOperator() == SQLUnionOperator.DISTINCT) && visitor.getConfig().isSelectUnionCheck())
|
||||
|| (x.getOperator() == SQLUnionOperator.MINUS && visitor.getConfig().isSelectMinusCheck())
|
||||
|| (x.getOperator() == SQLUnionOperator.INTERSECT && visitor.getConfig().isSelectIntersectCheck())
|
||||
|| (x.getOperator() == SQLUnionOperator.EXCEPT && visitor.getConfig().isSelectExceptCheck())) {
|
||||
addViolation(visitor, ErrorCode.UNION,
|
||||
x.getOperator().toString() + " query not contains 'from clause'", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1674,16 +1767,22 @@ public class WallVisitorUtils {
|
||||
}
|
||||
|
||||
if (checkSelectConst) {
|
||||
boolean allIsConst = true;
|
||||
for (SQLSelectItem item : queryBlock.getSelectList()) {
|
||||
if (getValue(visitor, item.getExpr()) == null) {
|
||||
allIsConst = false;
|
||||
break;
|
||||
SQLExpr where = queryBlock.getWhere();
|
||||
if (where != null) {
|
||||
Object whereValue = getValue(visitor, where);
|
||||
if (Boolean.TRUE == whereValue) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1710,17 +1809,20 @@ public class WallVisitorUtils {
|
||||
public static void loadResource(Set<String> names, String resource) {
|
||||
try {
|
||||
boolean hasResource = false;
|
||||
Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources(resource);
|
||||
while (e.hasMoreElements()) {
|
||||
URL url = e.nextElement();
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = url.openStream();
|
||||
readFromInputStream(names, in);
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
if (classLoader != null) {
|
||||
Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources(resource);
|
||||
while (e.hasMoreElements()) {
|
||||
URL url = e.nextElement();
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = url.openStream();
|
||||
readFromInputStream(names, in);
|
||||
|
||||
hasResource = true;
|
||||
} finally {
|
||||
JdbcUtils.close(in);
|
||||
hasResource = true;
|
||||
} finally {
|
||||
JdbcUtils.close(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user