diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 25124711f8..acf3c70ed1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1176,7 +1176,9 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.LPAREN) { lexer.nextToken(); - charType.getArguments().add(this.expr()); + SQLExpr arg = this.expr(); + arg.setParent(charType); + charType.getArguments().add(arg); accept(Token.RPAREN); } @@ -1195,7 +1197,7 @@ public class SQLExprParser extends SQLParser { protected SQLDataType parseDataTypeRest(SQLDataType dataType) { if (lexer.token() == Token.LPAREN) { lexer.nextToken(); - exprList(dataType.getArguments()); + exprList(dataType.getArguments(), dataType); accept(Token.RPAREN); } 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 d292574b37..1c3940bf54 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.visitor; import java.util.List; +import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLStatement; @@ -118,12 +119,24 @@ public class ParameterizedOutputVisitorUtils { } public static boolean visit(ParameterizedVisitor v, SQLIntegerExpr x) { + SQLObject parent = x.getParent(); + + if (parent instanceof SQLDataType) { + return SQLASTOutputVisitorUtils.visit(v, x); + } + v.print('?'); v.incrementReplaceCunt(); return false; } public static boolean visit(ParameterizedVisitor v, SQLNumberExpr x) { + SQLObject parent = x.getParent(); + + if (parent instanceof SQLDataType) { + return SQLASTOutputVisitorUtils.visit(v, x); + } + v.print('?'); v.incrementReplaceCunt(); return false; diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java index 45e3531aa6..348baa7d33 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java @@ -15,13 +15,10 @@ */ package com.alibaba.druid.sql.visitor; -public interface ParameterizedVisitor extends SQLASTVisitor { +public interface ParameterizedVisitor extends SQLPrintableVisitor { int getReplaceCount(); void incrementReplaceCunt(); - void print(char value); - - void print(String text); } 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 240be1f789..cbd639ddbc 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -120,7 +120,7 @@ import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.ast.statement.SQLUseStatement; import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause; -public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { +public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements SQLPrintableVisitor { protected final Appendable appender; private String indent = "\t"; @@ -485,8 +485,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLIntegerExpr x) { - print(x.getNumber().toString()); - return false; + return SQLASTOutputVisitorUtils.visit(this, x); } public boolean visit(SQLMethodInvokeExpr x) { @@ -555,8 +554,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLNumberExpr x) { - print(x.getNumber().toString()); - return false; + return SQLASTOutputVisitorUtils.visit(this, x); } public boolean visit(SQLPropertyExpr x) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitorUtils.java new file mode 100644 index 0000000000..db567b72c4 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitorUtils.java @@ -0,0 +1,17 @@ +package com.alibaba.druid.sql.visitor; + +import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; + +public class SQLASTOutputVisitorUtils { + + public static boolean visit(SQLPrintableVisitor visitor, SQLIntegerExpr x) { + visitor.print(x.getNumber().toString()); + return false; + } + + public static boolean visit(SQLPrintableVisitor visitor, SQLNumberExpr x) { + visitor.print(x.getNumber().toString()); + return false; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLPrintableVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLPrintableVisitor.java new file mode 100644 index 0000000000..bc251da9a0 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLPrintableVisitor.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.sql.visitor; + +public interface SQLPrintableVisitor extends SQLASTVisitor { + + void print(char value); + + void print(String text); +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_5.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_5.java new file mode 100644 index 0000000000..8467408ef6 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_5.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class MySqlParameterizedOutputVisitorTest_5 extends TestCase { + + public void test_0() throws Exception { + String sql = "ALTER TABLE `action_plans` ADD `kee` varchar(100)"; + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), sql); + } + + public void test_1() throws Exception { + String sql = "CREATE TABLE `snapshot_data` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `snapshot_id` integer, `resource_id` integer, `snapshot_data` mediumtext, `data_type` varchar(50), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin"; + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), sql); + } + + public void test_2() throws Exception { + String sql = "ALTER TABLE `active_rule_changes` ADD `username` varchar(200)"; + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), sql); + } + + public void test_3() throws Exception { + String sql = "CREATE TABLE `issue_changes` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `kee` varchar(50), `issue_key` varchar(50) NOT NULL, `user_login` varchar(40), `change_type` varchar(20), `change_data` mediumtext, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin"; + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), sql); + } +}