diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java index 4ce2750ce2..feb8404b3a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java @@ -4,13 +4,11 @@ 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.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; -import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleParameterizedOutputVisitor.java index c185269cf2..bd56ebba85 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleParameterizedOutputVisitor.java @@ -1,5 +1,6 @@ package com.alibaba.druid.sql.dialect.oracle.ast.visitor; +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; @@ -40,14 +41,14 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor { return super.visit(x); } - + public SQLBinaryOpExpr merge(SQLBinaryOpExpr x) { if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr) { x.getLeft().getAttributes().put(ATTR_PARAMS_SKIP, true); x.getRight().getAttributes().put(ATTR_PARAMS_SKIP, true); return x; } - + if (x.getRight() instanceof SQLLiteralExpr) { x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), new SQLVariantRefExpr("?")); } @@ -61,7 +62,7 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor { } if (x.getLeft() instanceof SQLBinaryOpExpr) { - x = new SQLBinaryOpExpr((SQLBinaryOpExpr) x.getLeft(), x.getOperator(), x.getRight()); + x = new SQLBinaryOpExpr(merge((SQLBinaryOpExpr) x.getLeft()), x.getOperator(), x.getRight()); } // ID = ? OR ID = ? => ID = ? @@ -70,27 +71,13 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor { SQLBinaryOpExpr left = (SQLBinaryOpExpr) x.getLeft(); SQLBinaryOpExpr right = (SQLBinaryOpExpr) x.getRight(); - if (left.getOperator() == SQLBinaryOperator.Equality && right.getOperator() == SQLBinaryOperator.Equality) { - if ((left.getLeft() instanceof SQLIdentifierExpr) && (right.getLeft() instanceof SQLIdentifierExpr)) { - String leftColumn = left.getLeft().toString(); - String rightColumn = right.getLeft().toString(); + if (mergeEqual(left, right)) { + return left; + } - if (leftColumn.equals(rightColumn)) { - if ((left.getRight() instanceof SQLVariantRefExpr) && (right.getRight() instanceof SQLVariantRefExpr)) { - return left; // merge - } - } - } - - if ((left.getLeft() instanceof SQLPropertyExpr) && (right.getLeft() instanceof SQLPropertyExpr)) { - String leftColumn = left.getLeft().toString(); - String rightColumn = right.getLeft().toString(); - - if (leftColumn.equals(rightColumn)) { - if ((left.getRight() instanceof SQLVariantRefExpr) && (right.getRight() instanceof SQLVariantRefExpr)) { - return left; // merge - } - } + if (isLiteralExpr(left.getLeft()) && left.getOperator() == SQLBinaryOperator.BooleanOr) { + if (mergeEqual(left.getRight(), right)) { + return left; } } } @@ -98,6 +85,49 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor { return x; } + + private boolean mergeEqual(SQLExpr a, SQLExpr b) { + if (!(a instanceof SQLBinaryOpExpr)) { + return false; + } + if (!(b instanceof SQLBinaryOpExpr)) { + return false; + } + + SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a; + SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b; + + if (binaryA.getOperator() != SQLBinaryOperator.Equality) { + return false; + } + + if (binaryB.getOperator() != SQLBinaryOperator.Equality) { + return false; + } + + if (!(binaryA.getRight() instanceof SQLLiteralExpr || binaryA.getRight() instanceof SQLVariantRefExpr)) { + return false; + } + + if (!(binaryB.getRight() instanceof SQLLiteralExpr || binaryB.getRight() instanceof SQLVariantRefExpr)) { + return false; + } + + return binaryA.getLeft().toString().equals(binaryB.getLeft().toString()); + } + + private boolean isLiteralExpr(SQLExpr expr) { + if (expr instanceof SQLLiteralExpr) { + return true; + } + + if (expr instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binary = (SQLBinaryOpExpr) expr; + return isLiteralExpr(binary.getLeft()) && isLiteralExpr(binary.getRight()); + } + + return false; + } public boolean visit(SQLIntegerExpr x) { if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) { diff --git a/src/test/java/com/alibaba/druid/sql/mysql/bvt/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/sql/mysql/bvt/MySqlParameterizedOutputVisitorTest.java index 22eafebe4d..cb313ec358 100644 --- a/src/test/java/com/alibaba/druid/sql/mysql/bvt/MySqlParameterizedOutputVisitorTest.java +++ b/src/test/java/com/alibaba/druid/sql/mysql/bvt/MySqlParameterizedOutputVisitorTest.java @@ -20,6 +20,7 @@ public class MySqlParameterizedOutputVisitorTest extends TestCase { validate("SELECT * FROM T WHERE ID = ? OR ID = ?", "SELECT * FROM T WHERE ID = ?"); validate("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT * FROM T WHERE A.ID = ?"); validate("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", "SELECT * FROM T WHERE 1 = 0 OR a.id = ?"); + validateOracle("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", "SELECT * FROM T WHERE 1 = 0 OR a.id = ?; "); validateOracle("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT * FROM T WHERE A.ID = ?; "); validate("INSERT INTO T (F1, F2) VALUES(?, ?), (?, ?), (?, ?)", "INSERT INTO T (F1, F2) VALUES (?, ?)");