diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java index ef7babe6b4..1706185630 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java @@ -33,7 +33,7 @@ public class SQLUnaryExpr extends SQLExprImpl implements Serializable { public SQLUnaryExpr(SQLUnaryOperator operator, SQLExpr expr){ this.operator = operator; - this.expr = expr; + this.setExpr(expr); } public SQLUnaryOperator getOperator() { @@ -49,6 +49,9 @@ public class SQLUnaryExpr extends SQLExprImpl implements Serializable { } public void setExpr(SQLExpr expr) { + if (expr != null) { + expr.setParent(this); + } this.expr = expr; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 7a1e78704e..80a6afd6d1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -826,7 +826,8 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public boolean visit(MySqlIntervalExpr x) { print0(ucase ? "INTERVAL " : "interval "); - x.getValue().accept(this); + SQLExpr value = x.getValue(); + value.accept(this); print(' '); print0(ucase ? x.getUnit().name() : x.getUnit().name_lcase); return false; 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 6f10b6afc4..8cba98c4be 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -463,10 +463,13 @@ public class SQLExprParser extends SQLParser { sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr); break; - case QUES: - sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, new SQLVariantRefExpr("?")); + case QUES: { + SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr("?"); + variantRefExpr.setIndex(lexer.nextVarIndex()); + sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, variantRefExpr); lexer.nextToken(); break; + } case LPAREN: lexer.nextToken(); sqlExpr = expr(); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_23.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_23.java index 69eb82c2a7..793bac9249 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_23.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_23.java @@ -50,8 +50,8 @@ public class MySqlParameterizedOutputVisitorTest_23 extends TestCase { visitor1.setParameters(visitor.getParameters()); stmt.accept(visitor1); - assertEquals("SELECT wmc_xxx_s_0479.fid\n" + + assertEquals("SELECT `wmc_xxx_s`.fid\n" + "FROM wmc_xxx_s_0479 `wmc_xxx_s`\n" + - "WHERE wmc_xxx_s_0479.fid = ?", buf.toString()); + "WHERE `wmc_xxx_s`.fid = ?", buf.toString()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_29.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_29.java new file mode 100644 index 0000000000..6f3c4b9fcc --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_29.java @@ -0,0 +1,90 @@ +package com.alibaba.druid.bvt.sql.mysql.param; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class MySqlParameterizedOutputVisitorTest_29 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + + String sql = "select `a1`.`id`,`a1`.`gmt_create`,`a1`.`gmt_modified`,`a1`.`push_date`,`a1`.`parent_task_id`" + + " ,`a1`.`parent_task_type`,`a1`.`action_type`,`a1`.`schedule_no`,`a1`.`type`,`a1`.`md5`" + + " ,`a1`.`message_content`,`a1`.`retry_count`,`a1`.`level`,`a1`.`extra`,`a1`.`status`" + + " ,`a1`.`is_exist_relation`,`a1`.`begin_time`,`a1`.`end_time`,`a1`.`orig`,`a1`.`dest`" + + " ,`a1`.`airline`,`a1`.`params_stat_id`,`a1`.`total_num`,`a1`.`finish_num`,`a1`.`type_idx_key`" + + " ,`a1`.`seqno`,`a1`.`task_flag`,`a1`.`tariff` " + + "from `xx_abcde_ta_0018` `a1` " + + "where ((`a1`.`push_date` = '2017-01-19 00:00:00') AND (`a1`.`schedule_no` <= '201701181201') AND (`a1`.`type` IN (1,4,2,3,7,8,11,12,13,14,15,16)) AND (`a1`.`retry_count` < 3) AND (`a1`.`status` IN (3,6)) AND (`a1`.`gmt_modified` <= DATE_ADD(NOW(),INTERVAL -(5) MINUTE))) limit 0,2000"; + + String psql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + assertEquals("SELECT `a1`.`id`, `a1`.`gmt_create`, `a1`.`gmt_modified`, `a1`.`push_date`, `a1`.`parent_task_id`\n" + + "\t, `a1`.`parent_task_type`, `a1`.`action_type`, `a1`.`schedule_no`, `a1`.`type`, `a1`.`md5`\n" + + "\t, `a1`.`message_content`, `a1`.`retry_count`, `a1`.`level`, `a1`.`extra`, `a1`.`status`\n" + + "\t, `a1`.`is_exist_relation`, `a1`.`begin_time`, `a1`.`end_time`, `a1`.`orig`, `a1`.`dest`\n" + + "\t, `a1`.`airline`, `a1`.`params_stat_id`, `a1`.`total_num`, `a1`.`finish_num`, `a1`.`type_idx_key`\n" + + "\t, `a1`.`seqno`, `a1`.`task_flag`, `a1`.`tariff`\n" + + "FROM xx_abcde_ta `a1`\n" + + "WHERE `a1`.`push_date` = ?\n" + + "\tAND `a1`.`schedule_no` <= ?\n" + + "\tAND `a1`.`type` IN (?)\n" + + "\tAND `a1`.`retry_count` < ?\n" + + "\tAND `a1`.`status` IN (?)\n" + + "\tAND `a1`.`gmt_modified` <= DATE_ADD(NOW(), INTERVAL -? MINUTE)\n" + + "LIMIT ?, ?", psql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + List stmtList = parser.parseStatementList(); + + StringBuilder out = new StringBuilder(); + SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, JdbcConstants.MYSQL); + List parameters = new ArrayList(); + visitor.setParameterized(true); + visitor.setParameterizedMergeInList(true); + visitor.setParameters(parameters); + visitor.setExportTables(true); + /*visitor.setPrettyFormat(false);*/ + + SQLStatement stmt = stmtList.get(0); + stmt.accept(visitor); + + // System.out.println(parameters); + assertEquals(8, parameters.size()); + + //SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(psql, dbType); + // List stmtList = parser.parseStatementList(); + SQLStatement pstmt = SQLUtils.parseStatements(psql, dbType).get(0); + + StringBuilder buf = new StringBuilder(); + SQLASTOutputVisitor visitor1 = SQLUtils.createOutputVisitor(buf, dbType); + visitor1.addTableMapping("xx_abcde_ta", "xx_abcde_ta_0018"); + visitor1.setParameters(visitor.getParameters()); + pstmt.accept(visitor1); + + assertEquals("SELECT `a1`.`id`, `a1`.`gmt_create`, `a1`.`gmt_modified`, `a1`.`push_date`, `a1`.`parent_task_id`\n" + + "\t, `a1`.`parent_task_type`, `a1`.`action_type`, `a1`.`schedule_no`, `a1`.`type`, `a1`.`md5`\n" + + "\t, `a1`.`message_content`, `a1`.`retry_count`, `a1`.`level`, `a1`.`extra`, `a1`.`status`\n" + + "\t, `a1`.`is_exist_relation`, `a1`.`begin_time`, `a1`.`end_time`, `a1`.`orig`, `a1`.`dest`\n" + + "\t, `a1`.`airline`, `a1`.`params_stat_id`, `a1`.`total_num`, `a1`.`finish_num`, `a1`.`type_idx_key`\n" + + "\t, `a1`.`seqno`, `a1`.`task_flag`, `a1`.`tariff`\n" + + "FROM xx_abcde_ta_0018 `a1`\n" + + "WHERE `a1`.`push_date` = '2017-01-19 00:00:00'\n" + + "\tAND `a1`.`schedule_no` <= '201701181201'\n" + + "\tAND `a1`.`type` IN (1, 4, 2, 3, 7, 8, 11, 12, 13, 14, 15, 16)\n" + + "\tAND `a1`.`retry_count` < 3\n" + + "\tAND `a1`.`status` IN (3, 6)\n" + + "\tAND `a1`.`gmt_modified` <= DATE_ADD(NOW(), INTERVAL -5 MINUTE)\n" + + "LIMIT 0, 2000", buf.toString()); + } +}