From cc8d00d78dc3845a46c3a6f1967654617bb2c866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Wed, 14 Mar 2012 23:56:58 +0800 Subject: [PATCH] add sql wall support --- .../filter/wall/spi/MySqlWallVisitor.java | 24 +++ .../filter/wall/spi/WallVisitorUtils.java | 138 +++++++++++++----- .../java/com/alibaba/druid/sql/SQLUtils.java | 3 +- .../bvt/filter/wall/WallVisitorUtilsTest.java | 6 + 4 files changed, 134 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java index e1b9663e55..73c1510b02 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java @@ -3,12 +3,17 @@ package com.alibaba.druid.filter.wall.spi; import java.util.ArrayList; import java.util.List; +import com.alibaba.druid.filter.wall.IllegalStatementViolation; import com.alibaba.druid.filter.wall.Violation; import com.alibaba.druid.filter.wall.WallVisitor; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTablesStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisitor { @@ -28,6 +33,25 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi } public boolean visit(MySqlExecuteStatement x) { + violations.add(new IllegalStatementViolation(SQLUtils.toMySqlString(x))); + return false; + } + + @Override + public boolean visit(MySqlShowTablesStatement x) { + violations.add(new IllegalStatementViolation(SQLUtils.toMySqlString(x))); + return false; + } + + @Override + public boolean visit(MySqlShowDatabasesStatement x) { + violations.add(new IllegalStatementViolation(SQLUtils.toMySqlString(x))); + return false; + } + + @Override + public boolean visit(MySqlShowColumnsStatement x) { + violations.add(new IllegalStatementViolation(SQLUtils.toMySqlString(x))); return false; } diff --git a/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java index 427ca7db98..b96b3091fe 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java @@ -7,8 +7,9 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; -import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLNotExpr; +import com.alibaba.druid.sql.ast.expr.SQLNullExpr; +import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; public class WallVisitorUtils { @@ -19,20 +20,106 @@ public class WallVisitorUtils { } } + @SuppressWarnings({ "unchecked", "rawtypes" }) public static Object getObject(SQLBinaryOpExpr x) { - if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr) { - if (x.getOperator() == SQLBinaryOperator.Equality) { - String leftLiteral = SQLUtils.toOracleString(x.getLeft()); - String rightLiteral = SQLUtils.toOracleString(x.getRight()); + x.getLeft().setParent(x); + x.getRight().setParent(x); + Object leftResult = getValue(x.getLeft()); + Object rightResult = getValue(x.getRight()); - return leftLiteral.equalsIgnoreCase(rightLiteral); + if (x.getOperator() == SQLBinaryOperator.BooleanOr) { + if (Boolean.TRUE == leftResult || Boolean.TRUE == rightResult) { + return true; + } + } + + if (x.getOperator() == SQLBinaryOperator.BooleanAnd) { + if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) { + return false; } - if (x.getOperator() == SQLBinaryOperator.NotEqual || x.getOperator() == SQLBinaryOperator.LessThanOrGreater) { - String leftLiteral = SQLUtils.toSQLString(x.getLeft()); - String rightLiteral = SQLUtils.toSQLString(x.getRight()); - - return !leftLiteral.equalsIgnoreCase(rightLiteral); + if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) { + return true; + } + } + + if (x.getOperator() == SQLBinaryOperator.Equality) { + if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { + return true; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + return leftResult.equals(rightResult); + } + + if (x.getOperator() == SQLBinaryOperator.NotEqual || x.getOperator() == SQLBinaryOperator.LessThanOrGreater) { + if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + return !leftResult.equals(rightResult); + } + + if (x.getOperator() == SQLBinaryOperator.GreaterThan) { + if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return (((Comparable) leftResult).compareTo(rightResult) > 0); + } + } + + if (x.getOperator() == SQLBinaryOperator.GreaterThanOrEqual) { + if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return ((Comparable) leftResult).compareTo(rightResult) >= 0; + } + } + + if (x.getOperator() == SQLBinaryOperator.LessThan) { + if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return (((Comparable) leftResult).compareTo(rightResult) < 0); + } + } + + if (x.getOperator() == SQLBinaryOperator.LessThanOrEqual) { + if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return ((Comparable) leftResult).compareTo(rightResult) <= 0; } } @@ -53,31 +140,6 @@ public class WallVisitorUtils { } } - x.getLeft().setParent(x); - x.getRight().setParent(x); - - if (x.getOperator() == SQLBinaryOperator.BooleanOr) { - Object leftResult = getValue(x.getLeft()); - Object rightResult = getValue(x.getRight()); - - if (Boolean.TRUE == leftResult || Boolean.TRUE == rightResult) { - return true; - } - } - - if (x.getOperator() == SQLBinaryOperator.BooleanAnd) { - Object leftResult = getValue(x.getLeft()); - Object rightResult = getValue(x.getRight()); - - if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) { - return false; - } - - if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) { - return true; - } - } - return null; } @@ -90,6 +152,10 @@ public class WallVisitorUtils { return ((MySqlBooleanExpr) x).getValue(); } + if (x instanceof SQLNumericLiteralExpr) { + return ((SQLNumericLiteralExpr) x).getNumber(); + } + if (x instanceof SQLNotExpr) { Object result = getValue(((SQLNotExpr) x).getExpr()); if (result != null && result instanceof Boolean) { diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 877712312b..6a8b442906 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -13,6 +13,7 @@ import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor; +import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.Token; @@ -116,7 +117,7 @@ public class SQLUtils { } public static SQLExpr toSQLExpr(String sql) { - MySqlLexer lexer = new MySqlLexer(sql); + Lexer lexer = new Lexer(sql); lexer.nextToken(); SQLExprParser parser = new SQLExprParser(lexer); diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallVisitorUtilsTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallVisitorUtilsTest.java index 83007269b2..24731dafb7 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallVisitorUtilsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallVisitorUtilsTest.java @@ -20,5 +20,11 @@ public class WallVisitorUtilsTest extends TestCase { Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 OR f1 like '%%'"))); Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("1 < 2"))); + Assert.assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 < 2"))); + Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 <= 2"))); + + Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 > 1"))); + Assert.assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 > 2"))); + Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 >= 2"))); } }