diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java index 8af62e1542..46c755b815 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java @@ -52,12 +52,6 @@ public class SQLUnaryExpr extends SQLExprImpl implements Serializable { this.expr = expr; } - @Override - public void output(StringBuffer buf) { - buf.append(" NOT "); - this.expr.output(buf); - } - protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, this.expr); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java index 03321992a9..9cc28348d3 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java @@ -30,7 +30,7 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen protected SQLDataType dataType; protected SQLExpr defaultExpr; protected final List constaints = new ArrayList(0); - protected String comment; + protected SQLExpr comment; protected Boolean enable; @@ -99,11 +99,11 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen visitor.endVisit(this); } - public String getComment() { + public SQLExpr getComment() { return comment; } - public void setComment(String comment) { + public void setComment(SQLExpr comment) { this.comment = comment; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2EvalVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2EvalVisitor.java index 112609f638..c8e9d3e194 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2EvalVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2EvalVisitor.java @@ -135,7 +135,7 @@ public class DB2EvalVisitor extends DB2ASTVisitorAdapter implements SQLEvalVisit public void registerFunction(String funcName, Function function) { functions.put(funcName, function); } - + public boolean visit(SQLIdentifierExpr x) { return SQLEvalVisitorUtils.visit(this, x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 87303587d2..9d1854a6d3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -558,12 +558,6 @@ public class MySqlExprParser extends SQLExprParser { throw new ParserException("syntax error " + lexer.token() + " " + lexer.stringVal()); } - if (lexer.token() == Token.COMMENT) { - lexer.nextToken(); - column.setComment(lexer.stringVal()); - accept(Token.LITERAL_CHARS); - } - if (identifierEquals("STORAGE")) { lexer.nextToken(); SQLExpr expr = expr(); @@ -727,7 +721,7 @@ public class MySqlExprParser extends SQLExprParser { if (lexer.token() == Token.KEY) { lexer.nextToken(); } - + if (lexer.token() == Token.INDEX) { lexer.nextToken(); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlEvalVisitorImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlEvalVisitorImpl.java index d479e2a50d..17c4314aab 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlEvalVisitorImpl.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlEvalVisitorImpl.java @@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; @@ -33,6 +34,7 @@ import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; import com.alibaba.druid.sql.visitor.SQLEvalVisitor; import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils; @@ -94,6 +96,14 @@ public class MySqlEvalVisitorImpl extends MySqlASTVisitorAdapter implements SQLE public boolean visit(SQLNumberExpr x) { return SQLEvalVisitorUtils.visit(this, x); } + + public boolean visit(SQLHexExpr x) { + return SQLEvalVisitorUtils.visit(this, x); + } + + public boolean visit(MySqlBinaryExpr x) { + return SQLEvalVisitorUtils.visit(this, x); + } @Override public boolean visit(SQLCaseExpr x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index b3940652e1..6f11ba6a0a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -324,6 +324,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print(' '); item.accept(this); } + + if (x.getComment() != null) { + print(" COMMENT "); + x.getComment().accept(this); + } return false; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleEvalVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleEvalVisitor.java index d1e03a5208..cd7176e10c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleEvalVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleEvalVisitor.java @@ -135,7 +135,7 @@ public class OracleEvalVisitor extends OracleASTVisitorAdapter implements SQLEva public void registerFunction(String funcName, Function function) { functions.put(funcName, function); } - + public boolean visit(SQLIdentifierExpr x) { return SQLEvalVisitorUtils.visit(this, x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGEvalVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGEvalVisitor.java index 1efd330256..6836039648 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGEvalVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGEvalVisitor.java @@ -135,7 +135,7 @@ public class PGEvalVisitor extends PGASTVisitorAdapter implements SQLEvalVisitor public void registerFunction(String funcName, Function function) { functions.put(funcName, function); } - + public boolean visit(SQLIdentifierExpr x) { return SQLEvalVisitorUtils.visit(this, x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerEvalVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerEvalVisitor.java index d24e664b2c..35ee8dfcad 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerEvalVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerEvalVisitor.java @@ -92,7 +92,7 @@ public class SQLServerEvalVisitor extends SQLServerASTVisitorAdapter implements public boolean visit(SQLNumberExpr x) { return SQLEvalVisitorUtils.visit(this, x); } - + @Override public boolean visit(SQLCaseExpr x) { return SQLEvalVisitorUtils.visit(this, x); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index c516d7185d..56ac42f7df 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1478,7 +1478,7 @@ public class SQLExprParser extends SQLParser { column.getConstaints().add(check); return parseColumnRest(column); } - + if (lexer.token == Token.DEFAULT) { lexer.nextToken(); SQLExpr expr = this.expr(); @@ -1494,6 +1494,11 @@ public class SQLExprParser extends SQLParser { column.getConstaints().add(check); return parseColumnRest(column); } + + if (lexer.token() == Token.COMMENT) { + lexer.nextToken(); + column.setComment(primary()); + } return column; } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorImpl.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorImpl.java index 2ec6156c09..52a52cf555 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorImpl.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorImpl.java @@ -23,6 +23,7 @@ import java.util.Map; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; @@ -86,6 +87,10 @@ public class SQLEvalVisitorImpl extends SQLASTVisitorAdapter implements SQLEvalV public boolean visit(SQLNumberExpr x) { return SQLEvalVisitorUtils.visit(this, x); } + + public boolean visit(SQLHexExpr x) { + return SQLEvalVisitorUtils.visit(this, x); + } @Override public boolean visit(SQLCaseExpr x) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index c8b60a86b2..3dfa190739 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.visitor; +import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_ERROR; import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_EXPR; import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE; import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE_NULL; @@ -40,6 +41,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -53,6 +55,7 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.visitor.DB2EvalVisitor; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleEvalVisitor; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGEvalVisitor; @@ -84,6 +87,7 @@ import com.alibaba.druid.sql.visitor.functions.Substring; import com.alibaba.druid.sql.visitor.functions.Trim; import com.alibaba.druid.sql.visitor.functions.Ucase; import com.alibaba.druid.sql.visitor.functions.Unhex; +import com.alibaba.druid.util.HexBin; import com.alibaba.druid.util.JdbcUtils; import com.alibaba.druid.wall.spi.WallVisitorUtils; import com.alibaba.druid.wall.spi.WallVisitorUtils.WallConditionContext; @@ -192,6 +196,7 @@ public class SQLEvalVisitorUtils { functions.put("lpad", Lpad.instance); functions.put("ltrim", Ltrim.instance); functions.put("mid", Substring.instance); + functions.put("substr", Substring.instance); functions.put("substring", Substring.instance); functions.put("right", Right.instance); functions.put("reverse", Reverse.instance); @@ -554,6 +559,19 @@ public class SQLEvalVisitorUtils { return true; } + public static boolean visit(SQLEvalVisitor visitor, SQLHexExpr x) { + String hex = x.getHex(); + byte[] bytes = HexBin.decode(hex); + String val = new String(bytes); + x.putAttribute(EVAL_VALUE, val); + return true; + } + + public static boolean visit(SQLEvalVisitor visitor, MySqlBinaryExpr x) { + + return true; + } + public static boolean visit(SQLEvalVisitor visitor, SQLBetweenExpr x) { x.getTestExpr().accept(visitor); @@ -715,6 +733,36 @@ public class SQLEvalVisitorUtils { wallConditionContext.setBitwise(true); } + x.getExpr().accept(visitor); + + Object val = x.getExpr().getAttribute(EVAL_VALUE); + if (val == EVAL_ERROR) { + x.putAttribute(EVAL_VALUE, EVAL_ERROR); + return false; + } + + switch (x.getOperator()) { + case BINARY: + case RAW: + x.putAttribute(EVAL_VALUE, val); + break; + case NOT: + case Not: + x.putAttribute(EVAL_VALUE, !castToBoolean(val)); + break; + case Plus: + x.putAttribute(EVAL_VALUE, val); + break; + case Negative: + x.putAttribute(EVAL_VALUE, multi(val, -1)); + break; + case Compl: + x.putAttribute(EVAL_VALUE, ~castToInteger(val)); + break; + default: + break; + } + return false; } @@ -834,6 +882,18 @@ public class SQLEvalVisitorUtils { value = div(leftValue, rightValue); x.putAttribute(EVAL_VALUE, value); break; + case RightShift: + value = rightShift(leftValue, rightValue); + x.putAttribute(EVAL_VALUE, value); + break; + case BitwiseAnd: + value = bitAnd(leftValue, rightValue); + x.putAttribute(EVAL_VALUE, value); + break; + case BitwiseOr: + value = bitOr(leftValue, rightValue); + x.putAttribute(EVAL_VALUE, value); + break; case GreaterThan: value = gt(leftValue, rightValue); x.putAttribute(EVAL_VALUE, value); @@ -978,7 +1038,17 @@ public class SQLEvalVisitorUtils { } if (val instanceof Number) { - return ((Number) val).intValue() == 1; + return ((Number) val).intValue() > 0; + } + + if (val instanceof String) { + if ("1".equals(val) || "true".equalsIgnoreCase((String) val)) { + return true; + } + + if ("0".equals(val) || "false".equalsIgnoreCase((String) val)) { + return false; + } } throw new IllegalArgumentException(val.getClass() + " not supported."); @@ -1186,6 +1256,42 @@ public class SQLEvalVisitorUtils { return BigDecimal.valueOf(((Number) val).longValue()); } + public static Object rightShift(Object a, Object b) { + if (a == null || b == null) { + return null; + } + + if (a instanceof Long || b instanceof Long) { + return castToLong(a).longValue() >> castToLong(b).longValue(); + } + + return castToInteger(a).intValue() >> castToInteger(b).intValue(); + } + + public static Object bitAnd(Object a, Object b) { + if (a == null || b == null) { + return null; + } + + if (a instanceof Long || b instanceof Long) { + return castToLong(a).longValue() & castToLong(b).longValue(); + } + + return castToInteger(a).intValue() & castToInteger(b).intValue(); + } + + public static Object bitOr(Object a, Object b) { + if (a == null || b == null) { + return null; + } + + if (a instanceof Long || b instanceof Long) { + return castToLong(a).longValue() | castToLong(b).longValue(); + } + + return castToInteger(a).intValue() | castToInteger(b).intValue(); + } + public static Object div(Object a, Object b) { if (a == null || b == null) { return null; diff --git a/src/main/java/com/alibaba/druid/sql/visitor/functions/Ascii.java b/src/main/java/com/alibaba/druid/sql/visitor/functions/Ascii.java index 5423220687..4eb08824b0 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/functions/Ascii.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/functions/Ascii.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.visitor.functions; import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE; +import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE_NULL; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -31,15 +32,19 @@ public class Ascii implements Function { } SQLExpr param = x.getParameters().get(0); param.accept(visitor); - + Object paramValue = param.getAttributes().get(EVAL_VALUE); if (paramValue == null) { return SQLEvalVisitor.EVAL_ERROR; } + + if (paramValue == EVAL_VALUE_NULL) { + return EVAL_VALUE_NULL; + } String strValue = paramValue.toString(); if (strValue.length() == 0) { - return SQLEvalVisitor.EVAL_ERROR; + return 0; } int ascii = strValue.charAt(0); diff --git a/src/main/java/com/alibaba/druid/wall/WallVisitor.java b/src/main/java/com/alibaba/druid/wall/WallVisitor.java index 27ddc0e91d..5e2676ebd7 100644 --- a/src/main/java/com/alibaba/druid/wall/WallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/WallVisitor.java @@ -37,4 +37,6 @@ public interface WallVisitor extends SQLASTVisitor { boolean isSqlModified(); void setSqlModified(boolean sqlModified); + + String getDbType(); } diff --git a/src/main/java/com/alibaba/druid/wall/spi/DB2WallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/DB2WallVisitor.java index b0084bf94b..69a9a61790 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/DB2WallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/DB2WallVisitor.java @@ -43,6 +43,7 @@ import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitorAdapter; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.wall.Violation; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallProvider; @@ -62,6 +63,11 @@ public class DB2WallVisitor extends DB2ASTVisitorAdapter implements WallVisitor this.provider = provider; } + @Override + public String getDbType() { + return JdbcConstants.DB2; + } + @Override public boolean isSqlModified() { return sqlModified; diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java index 2f89adad3b..b3b52e26b8 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java @@ -57,6 +57,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.wall.Violation; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallContext; @@ -77,6 +78,11 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi this.config = provider.getConfig(); this.provider = provider; } + + @Override + public String getDbType() { + return JdbcConstants.MYSQL; + } @Override public boolean isSqlModified() { diff --git a/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java index 9e2df7c7a5..b310a4da59 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java @@ -51,6 +51,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.wall.Violation; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallProvider; @@ -69,6 +70,11 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi this.config = provider.getConfig(); this.provider = provider; } + + @Override + public String getDbType() { + return JdbcConstants.ORACLE; + } @Override public boolean isSqlModified() { diff --git a/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java index 3ac9c316f8..ffebe12924 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java @@ -43,6 +43,7 @@ import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.wall.Violation; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallProvider; @@ -61,6 +62,11 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor { this.config = provider.getConfig(); this.provider = provider; } + + @Override + public String getDbType() { + return JdbcConstants.POSTGRESQL; + } @Override public boolean isSqlModified() { diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java index 88b69f50c4..7731795ae8 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java @@ -47,6 +47,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReference import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.wall.Violation; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallProvider; @@ -65,6 +66,11 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements this.config = provider.getConfig(); this.provider = provider; } + + @Override + public String getDbType() { + return JdbcConstants.SQL_SERVER; + } @Override public boolean isSqlModified() { diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index 5d42d097bd..6195bd67c0 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -47,6 +47,7 @@ import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; @@ -612,8 +613,10 @@ public class WallVisitorUtils { boolean allFalse = true; for (int i = groupList.size() - 1; i >= 0; --i) { - Object result = getValue(visitor, groupList.get(i)); - if (Boolean.TRUE == result) { + 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 && i != 0) { wallContext.setPartAlwayTrue(true); @@ -621,7 +624,7 @@ public class WallVisitorUtils { return true; } - if (Boolean.FALSE != result) { + if (Boolean.FALSE != booleanVal) { allFalse = false; } } @@ -973,63 +976,14 @@ public class WallVisitorUtils { } } - if (x instanceof SQLMethodInvokeExpr) { - return getValue(visitor, (SQLMethodInvokeExpr) x); + if (x instanceof SQLMethodInvokeExpr || x instanceof SQLUnaryExpr) { + String dbType = null; + if (visitor != null) { + dbType = visitor.getDbType(); + } + return SQLEvalVisitorUtils.eval(dbType, x, Collections.emptyList(), false); } - - return null; - } - - public static Object getValue(WallVisitor visitor, SQLMethodInvokeExpr x) { - String methodName = x.getMethodName(); - if ("len".equalsIgnoreCase(methodName) || "length".equalsIgnoreCase(methodName)) { - Object firstValue = null; - if (x.getParameters().size() > 0) { - firstValue = (getValue(visitor, x.getParameters().get(0))); - } - - if (firstValue instanceof String) { - return ((String) firstValue).length(); - } - } - - if ("if".equalsIgnoreCase(methodName) && x.getParameters().size() == 3) { - SQLExpr first = x.getParameters().get(0); - Object firstResult = getValue(visitor, first); - - if (Boolean.TRUE == firstResult) { - return getValue(visitor, x.getParameters().get(1)); - } - - if (Boolean.FALSE == firstResult) { - getValue(visitor, x.getParameters().get(2)); - } - } - - if ("chr".equalsIgnoreCase(methodName) && x.getParameters().size() == 1) { - SQLExpr first = x.getParameters().get(0); - Object firstResult = getValue(visitor, first); - if (firstResult instanceof Number) { - int intValue = ((Number) firstResult).intValue(); - char ch = (char) intValue; - - return "" + ch; - } - } - - if ("concat".equalsIgnoreCase(methodName)) { - StringBuffer buf = new StringBuffer(); - for (SQLExpr expr : x.getParameters()) { - Object value = getValue(visitor, expr); - if (value == null) { - return null; - } - - buf.append(value.toString()); - } - return buf.toString(); - } - + return null; } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfTest.java b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfTest.java index 5b63a7a943..0b31e91224 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfTest.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfTest.java @@ -33,7 +33,7 @@ public class MySqlPerfTest extends TestCase { sql = "SELECT * FROM T"; sql = "SELECT ID, NAME, AGE FROM USER WHERE ID = ?"; - sql = Utils.readFromResource("benchmark/sql/ob_sql.txt"); +// sql = Utils.readFromResource("benchmark/sql/ob_sql.txt"); } public void test_pert() throws Exception { @@ -48,7 +48,7 @@ public class MySqlPerfTest extends TestCase { long startFGC = TestUtils.getFullGC(); long startMillis = System.currentTimeMillis(); - for (int i = 0; i < 1000 * 1; ++i) { + for (int i = 0; i < 1000 * 1000; ++i) { execMySql(sql); } long millis = System.currentTimeMillis() - startMillis; diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest100.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest100.java new file mode 100644 index 0000000000..b8dbdd0293 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest100.java @@ -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 MySqlWallTest100 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or substr(bin(97>>6), -1, 1) = 1"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest101.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest101.java new file mode 100644 index 0000000000..c0801ff032 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest101.java @@ -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 MySqlWallTest101 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or substr(bin(97>>6), -1, 1)"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest102.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest102.java new file mode 100644 index 0000000000..55c3b84cb4 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest102.java @@ -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 MySqlWallTest102 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or substr(bin(97>>5), -1, 1)"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest103.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest103.java new file mode 100644 index 0000000000..50aa9f24f8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest103.java @@ -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 MySqlWallTest103 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or 97 & 1"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest104.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest104.java new file mode 100644 index 0000000000..8de5a3dfeb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest104.java @@ -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 MySqlWallTest104 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or 97 | 1"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest105.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest105.java new file mode 100644 index 0000000000..07436a0dda --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest105.java @@ -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 MySqlWallTest105 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or binary true"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest97.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest97.java new file mode 100644 index 0000000000..01b9c867c8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest97.java @@ -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 MySqlWallTest97 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or ascii(141) = 49"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest98.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest98.java new file mode 100644 index 0000000000..a482ff387e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest98.java @@ -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 MySqlWallTest98 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or ascii(0x7F) = 127"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest99.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest99.java new file mode 100644 index 0000000000..fa6e1c3a2b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest99.java @@ -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 MySqlWallTest99 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "select * from t where id = ? or substr(bin(97>>7), -1, 1) = 0"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest50.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest50.java new file mode 100644 index 0000000000..a3f1ea0c7a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest50.java @@ -0,0 +1,60 @@ +/* + * 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 org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +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; + +public class MySqlCreateTableTest50 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE TABLE `test`.`a` (" // + + " `ida` INT NOT NULL COMMENT 'aaa' ,"// + + " PRIMARY KEY (`ida`) )"// + + " COMMENT = 'bb';"; // + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseCreateTable(); + + 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(1, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("test.a"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("CREATE TABLE `test`.`a` (" // + + "\n\t`ida` INT NOT NULL COMMENT 'aaa', "// + + "\n\tPRIMARY KEY (`ida`)"// + + "\n) COMMENT = 'bb'",// + output); + + } +}