diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java index b580203af8..8d37929ab4 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -71,6 +71,12 @@ public class ParameterizedOutputVisitorUtils { } } + public static String parameterize(String sql + , String dbType + , List outParameters, VisitorFeature ...features) { + return parameterize(sql, dbType, null, outParameters, features); + } + public static String parameterize(String sql , String dbType , SQLSelectListCache selectListCache, List outParameters, VisitorFeature ...visitorFeatures) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 3806840fb5..827b9f7824 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -520,45 +520,47 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet List literalItems = null; - for (int i = 0; i < items.size(); i++) { - SQLExpr item = items.get(i); - if (item instanceof SQLBinaryOpExpr) { - SQLBinaryOpExpr binaryItem = (SQLBinaryOpExpr) item; - SQLExpr left = binaryItem.getLeft(); - SQLExpr right = binaryItem.getRight(); + if (operator != SQLBinaryOperator.BooleanOr || !isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeOr)) { + for (int i = 0; i < items.size(); i++) { + SQLExpr item = items.get(i); + if (item instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryItem = (SQLBinaryOpExpr) item; + SQLExpr left = binaryItem.getLeft(); + SQLExpr right = binaryItem.getRight(); - if (right instanceof SQLLiteralExpr && !(right instanceof SQLNullExpr)) { - if (left instanceof SQLLiteralExpr) { - if (literalItems == null) { - literalItems = new ArrayList(); + if (right instanceof SQLLiteralExpr && !(right instanceof SQLNullExpr)) { + if (left instanceof SQLLiteralExpr) { + if (literalItems == null) { + literalItems = new ArrayList(); + } + literalItems.add(binaryItem); + continue; } - literalItems.add(binaryItem); - continue; + + if (this.parameters != null) { + ExportParameterVisitorUtils.exportParameter(parameters, right); + } + } else if (right instanceof SQLVariantRefExpr) { + // skip + } else { + firstLeft = null; + break; } - if (this.parameters != null) { - ExportParameterVisitorUtils.exportParameter(parameters, right); + + if (firstLeft == null) { + firstLeft = binaryItem.getLeft(); + firstOp = binaryItem.getOperator(); + } else { + if (!SQLExprUtils.equals(firstLeft, left)) { + firstLeft = null; + break; + } } - } else if (right instanceof SQLVariantRefExpr) { - // skip } else { firstLeft = null; break; } - - - if (firstLeft == null) { - firstLeft = binaryItem.getLeft(); - firstOp = binaryItem.getOperator(); - } else { - if (!SQLExprUtils.equals(firstLeft, left)) { - firstLeft = null; - break; - } - } - } else { - firstLeft = null; - break; } } @@ -653,7 +655,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLBinaryOpExpr x) { SQLBinaryOperator operator = x.getOperator(); if (this.parameterized - && operator == SQLBinaryOperator.BooleanOr) { + && operator == SQLBinaryOperator.BooleanOr + && !isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeOr)) { x = SQLBinaryOpExpr.merge(this, x); operator = x.getOperator(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java b/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java index 5a69823cfe..c7f21c996f 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java @@ -24,6 +24,7 @@ public enum VisitorFeature { OutputSkipSelectListCacheString, OutputSkipInsertColumnsString, OutputParameterizedQuesUnMergeInList, + OutputParameterizedQuesUnMergeOr, /** * @deprecated diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_75_or.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_75_or.java new file mode 100644 index 0000000000..45c4e23ef3 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_75_or.java @@ -0,0 +1,57 @@ +package com.alibaba.druid.bvt.sql.mysql.param; + +import com.alibaba.fastjson.JSON; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.sql.visitor.ParameterizedVisitor; +import com.alibaba.druid.sql.visitor.VisitorFeature; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +public class MySqlParameterizedOutputVisitorTest_75_or extends TestCase { + public void test_or() throws Exception { + + String sql = "select * from t1 where id = 1 or id = 2 or id = 3"; + + List outParameters = new ArrayList(0); + + String psql = ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL, outParameters, VisitorFeature.OutputParameterizedQuesUnMergeOr); + assertEquals("SELECT *\n" + + "FROM t1\n" + + "WHERE id = ?\n" + + "\tOR id = ?\n" + + "\tOR id = ?", psql); + + assertEquals("[1,2,3]", JSON.toJSONString(outParameters)); + } + + public void test_or_2() throws Exception { + + String sql = "select * from t1 where id = 1 or id = 2 or id = 3"; + + List outParameters = new ArrayList(0); + + SQLStatement stmt = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL).get(0); + + StringBuilder out = new StringBuilder(sql.length()); + ParameterizedVisitor visitor = ParameterizedOutputVisitorUtils.createParameterizedOutputVisitor(out, JdbcConstants.MYSQL); + visitor.config(VisitorFeature.OutputParameterizedQuesUnMergeOr, true); + if (outParameters != null) { + visitor.setOutputParameters(outParameters); + } + stmt.accept(visitor); + + String psql = out.toString(); + assertEquals("SELECT *\n" + + "FROM t1\n" + + "WHERE id = ?\n" + + "\tOR id = ?\n" + + "\tOR id = ?", psql); + + assertEquals("[1,2,3]", JSON.toJSONString(outParameters)); + } +}