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 250464c7cf..4ce2750ce2 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 @@ -1,5 +1,6 @@ package com.alibaba.druid.sql.dialect.mysql.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; @@ -49,7 +50,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { x.getRight().getAttributes().put(ATTR_PARAMS_SKIP, true); return x; } - + if (x.getRight() instanceof SQLLiteralExpr) { x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), new SQLVariantRefExpr("?")); } @@ -72,27 +73,13 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { 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; } } } @@ -101,11 +88,54 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { 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))) { return super.visit(x); } - + print('?'); return false; } @@ -114,7 +144,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) { return super.visit(x); } - + print('?'); return false; } @@ -123,7 +153,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) { return super.visit(x); } - + print('?'); return false; } @@ -132,7 +162,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) { return super.visit(x); } - + print('?'); return false; } 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 6a4976b257..a95bf5eb2c 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 @@ -19,10 +19,11 @@ public class MySqlParameterizedOutputVisitorTest extends TestCase { validate("SELECT * FROM T WHERE 1 = 0 AND ID = 5", "SELECT * FROM T WHERE 1 = 0 AND ID = ?"); 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 = ?", "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 (?, ?)"); - System.out.println("SELECT * FORM A WHERE ID = (##)".replaceAll("##", "?")); + //System.out.println("SELECT * FORM A WHERE ID = (##)".replaceAll("##", "?")); } void validate(String sql, String expect) { diff --git a/src/test/resources/bvt/parser/mysql-9.txt b/src/test/resources/bvt/parser/mysql-9.txt index 0efed3000a..9f7838f15e 100644 --- a/src/test/resources/bvt/parser/mysql-9.txt +++ b/src/test/resources/bvt/parser/mysql-9.txt @@ -8,4 +8,4 @@ WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id ORDER BY lastChangeTimeOfAlarmRule DESC LIMIT ?, ? --------------------------- -SELECT a.id AS "appId", a.name AS "appName", b.number AS "instanceNumber", b.hostname AS "hostname", c.name AS "monitorItemName" , d.id AS "alarmRuleStatusId", d.name AS "alarmRuleName", d.current_status AS "alarmRuleStatus", d.last_change_time AS "lastChangeTimeOfAlarmRule" FROM mi_alarm_rule_status d LEFT JOIN monitor_item_status c ON d.mi_status_id = c.id LEFT JOIN instance b ON b.number = c.inst_num AND b.app_num = c.app_num AND b.hostname = c.hostname LEFT JOIN app a ON a.number = b.app_num WHERE ? = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? ORDER BY lastChangeTimeOfAlarmRule DESC LIMIT ?, ? \ No newline at end of file +SELECT a.id AS "appId", a.name AS "appName", b.number AS "instanceNumber", b.hostname AS "hostname", c.name AS "monitorItemName" , d.id AS "alarmRuleStatusId", d.name AS "alarmRuleName", d.current_status AS "alarmRuleStatus", d.last_change_time AS "lastChangeTimeOfAlarmRule" FROM mi_alarm_rule_status d LEFT JOIN monitor_item_status c ON d.mi_status_id = c.id LEFT JOIN instance b ON b.number = c.inst_num AND b.app_num = c.app_num AND b.hostname = c.hostname LEFT JOIN app a ON a.number = b.app_num WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ? ORDER BY lastChangeTimeOfAlarmRule DESC LIMIT ?, ? \ No newline at end of file