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 602ca017b4..f2802a8096 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -61,9 +61,18 @@ public class ParameterizedOutputVisitorUtils { return parameterize(sql, dbType, null, outParameters); } + + private static void configVisitorFeatures(ParameterizedVisitor visitor, VisitorFeature ...features) { + if(features != null) { + for (int i = 0; i < features.length; i++) { + visitor.config(features[i], true); + } + } + } + public static String parameterize(String sql , String dbType - , SQLSelectListCache selectListCache, List outParameters) { + , SQLSelectListCache selectListCache, List outParameters, VisitorFeature ...visitorFeatures) { final SQLParserFeature[] features = outParameters == null ? defaultFeatures2 @@ -85,6 +94,7 @@ public class ParameterizedOutputVisitorUtils { if (outParameters != null) { visitor.setOutputParameters(outParameters); } + configVisitorFeatures(visitor, visitorFeatures); for (int i = 0; i < statementList.size(); i++) { SQLStatement stmt = statementList.get(i); @@ -133,13 +143,13 @@ public class ParameterizedOutputVisitorUtils { public static long parameterizeHash(String sql , String dbType , List outParameters) { - return parameterizeHash(sql, dbType, null, outParameters); + return parameterizeHash(sql, dbType, null, outParameters, null); } public static long parameterizeHash(String sql , String dbType , SQLSelectListCache selectListCache - , List outParameters) { + , List outParameters, VisitorFeature ...visitorFeatures) { final SQLParserFeature[] features = outParameters == null ? defaultFeatures2 @@ -162,6 +172,7 @@ public class ParameterizedOutputVisitorUtils { if (outParameters != null) { visitor.setOutputParameters(outParameters); } + configVisitorFeatures(visitor, visitorFeatures); if (stmtSize == 1) { SQLStatement stmt = statementList.get(0); 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 2931da8ad2..91cb73a7c5 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -77,6 +77,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet protected int replaceCount; protected boolean parameterizedMergeInList = false; + protected boolean parameterizedQuesUnMergeInList = false; protected boolean parameterized = false; protected boolean shardingSupport = false; @@ -102,6 +103,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public SQLASTOutputVisitor(Appendable appender, boolean parameterized){ this.appender = appender; this.config(VisitorFeature.OutputParameterized, parameterized); + this.config(VisitorFeature.OutputParameterizedQuesUnMergeInList, parameterizedQuesUnMergeInList); } public int getReplaceCount() { @@ -216,6 +218,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet this.parameterizedMergeInList = parameterizedMergeInList; } + public boolean isParameterizedQuesUnMergeInList() { + return isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeInList); + } + + public void setParameterizedQuesUnMergeInList(boolean parameterizedQuesUnMergeInList) { + config(VisitorFeature.OutputParameterizedQuesUnMergeInList, parameterizedQuesUnMergeInList); + } + public boolean isExportTables() { return exportTables; } @@ -1208,9 +1218,22 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printExpr(x.getExpr()); if (x.isNot()) { - print(ucase ? " NOT IN (?)" : " not in (?)"); + print(ucase ? " NOT" : " not"); } else { - print(ucase ? " IN (?)" : " in (?)"); + print(ucase ? " IN" : " in"); + } + + if(!isParameterizedQuesUnMergeInList() || targetList.size() == 1) { + print(" (?)"); + } else { + print(" ("); + for (int i = 0; i < targetList.size(); i++) { + if(i != 0) { + print(","); + } + print(" ?"); + } + print(")"); } if (changed) { @@ -5794,6 +5817,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet super.setFeatures(features); this.ucase = isEnabled(VisitorFeature.OutputUCase); this.parameterized = isEnabled(VisitorFeature.OutputParameterized); + this.parameterizedQuesUnMergeInList = isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeInList); } /////////////// for oracle 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 8bdba1b6b1..514c19f74b 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java @@ -23,6 +23,7 @@ public enum VisitorFeature { OutputUseInsertValueClauseOriginalString, OutputSkipSelectListCacheString, OutputSkipInsertColumnsString, + OutputParameterizedQuesUnMergeInList ; private VisitorFeature(){ diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/SQL_Parser_Parameterize_Test.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/SQL_Parser_Parameterize_Test.java index f14359d0da..c4e444170a 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/SQL_Parser_Parameterize_Test.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/SQL_Parser_Parameterize_Test.java @@ -16,6 +16,7 @@ package com.alibaba.druid.bvt.sql.mysql.param; import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.sql.visitor.VisitorFeature; import com.alibaba.druid.util.JdbcConstants; import junit.framework.TestCase; @@ -40,4 +41,23 @@ public class SQL_Parser_Parameterize_Test extends TestCase { assertEquals(102, outParameters.get(1)); assertEquals("wenshao", outParameters.get(2)); } + + public void test_parameterized_2() throws Exception { + final String dbType = JdbcConstants.MYSQL; + + List outParameters = new ArrayList(); + String sql = "select * from t where id = 101 or id in (1,2,3,4)"; + String psql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType, null, outParameters, VisitorFeature.OutputParameterizedQuesUnMergeInList); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE id = ?\n" + + "\tOR id IN ( ?, ?, ?, ?)", psql); + + assertEquals(5, outParameters.size()); + assertEquals(101, outParameters.get(0)); + assertEquals(1, outParameters.get(1)); + assertEquals(2, outParameters.get(2)); + assertEquals(3, outParameters.get(3)); + assertEquals(4, outParameters.get(4)); + } }