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 bc5a356822..4da42b54d5 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -209,7 +209,7 @@ public class ParameterizedOutputVisitorUtils { // ID = ? OR ID = ? => ID = ? if (x.getOperator() == SQLBinaryOperator.BooleanOr) { - if ((left instanceof SQLBinaryOpExpr) && (right instanceof SQLBinaryOpExpr)) { + if ((x.getLeft() instanceof SQLBinaryOpExpr) && (x.getRight() instanceof SQLBinaryOpExpr)) { SQLBinaryOpExpr leftBinary = (SQLBinaryOpExpr) x.getLeft(); SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.getRight(); @@ -220,7 +220,7 @@ public class ParameterizedOutputVisitorUtils { if (isLiteralExpr(leftBinary.getLeft()) // && leftBinary.getOperator() == SQLBinaryOperator.BooleanOr) { - if (mergeEqual(leftBinary.getRight(), right)) { + if (mergeEqual(leftBinary.getRight(), x.getRight())) { v.incrementReplaceCunt(); return leftBinary; } 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 032e772b87..0c0035adfc 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -846,7 +846,26 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLPropertyExpr x) { SQLExpr owner = x.getOwner(); - owner.accept(this); + String mapTableName = null; + if (owner instanceof SQLIdentifierExpr) { + String ownerName = ((SQLIdentifierExpr) owner).getName(); + if (tableMapping != null) { + mapTableName = tableMapping.get(ownerName); + + if (mapTableName == null + && ownerName.length() > 2 + && ownerName.charAt(0) == '`' + && ownerName.charAt(ownerName.length() - 1) == '`') { + mapTableName = tableMapping.get(ownerName.substring(1, ownerName.length() - 1)); + } + } + } + + if (mapTableName != null) { + print0(mapTableName); + } else { + owner.accept(this); + } print('.'); String name = x.getName(); @@ -1096,7 +1115,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet protected void addTable(String table) { if (tables == null) { - tables = new HashSet(); + tables = new LinkedHashSet(); } this.tables.add(table); } @@ -1110,6 +1129,29 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet String tableName = expr.toString(); String destTableName = tableMapping.get(tableName); + if (destTableName == null) { + if (expr instanceof SQLPropertyExpr) { + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; + String propName = propertyExpr.getName(); + destTableName = tableMapping.get(propName); + if (destTableName == null + && propName.length() > 2 && propName.charAt(0) == '`' && propName.charAt(propName.length() - 1) == '`') { + destTableName = tableMapping.get(propName.substring(1, propName.length() - 1)); + } + + if (destTableName != null) { + propertyExpr.getOwner().accept(this); + print('.'); + print(destTableName); + return; + } + } else if (expr instanceof SQLIdentifierExpr) { + boolean quote = tableName.length() > 2 && tableName.charAt(0) == '`' && tableName.charAt(tableName.length() - 1) == '`'; + if (quote) { + destTableName = tableMapping.get(tableName.substring(1, tableName.length() - 1)); + } + } + } if (destTableName != null) { tableName = destTableName; print0(tableName); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index a0b0a48392..0e9910e87d 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -78,7 +78,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { protected final Map variants = new LinkedHashMap(); - protected Map aliasMap = new HashMap(); + protected Map aliasMap = new LinkedHashMap(); protected String currentTable; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_19.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_19.java new file mode 100644 index 0000000000..ab8113d006 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_19.java @@ -0,0 +1,56 @@ +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.Collections; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class MySqlParameterizedOutputVisitorTest_19 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + + String sql = "SELECT COUNT(*), xx_id FROM `a_lb`.lb_release_source_aio GROUP BY xx_id"; + + String psql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + assertEquals("SELECT COUNT(*), xx_id FROM `a_lb`.lb_release_source_aio GROUP BY xx_id", 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(0, parameters.size()); + + StringBuilder buf = new StringBuilder(); + SQLASTOutputVisitor visitor1 = SQLUtils.createOutputVisitor(buf, dbType); + visitor1.addTableMapping("lb_release_source_aio", "lb_release_source_aio_0008"); + visitor1.setParameters(visitor.getParameters()); + stmt.accept(visitor1); + + assertEquals("SELECT COUNT(*), xx_id\n" + + "FROM `a_lb`.lb_release_source_aio_0008\n" + + "GROUP BY xx_id", buf.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_20.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_20.java new file mode 100644 index 0000000000..6fbc2a35fb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_20.java @@ -0,0 +1,55 @@ +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_20 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + + String sql = "select `a_entry_2664`.`id` from `a_entry_2664`"; + + String psql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + assertEquals("SELECT a_entry.`id`\n" + + "FROM a_entry", psql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(psql, 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(0, parameters.size()); + + StringBuilder buf = new StringBuilder(); + SQLASTOutputVisitor visitor1 = SQLUtils.createOutputVisitor(buf, dbType); + visitor1.addTableMapping("a_entry", "a_entry_2664"); + visitor1.setParameters(visitor.getParameters()); + stmt.accept(visitor1); + + assertEquals("SELECT a_entry_2664.`id`\n" + + "FROM a_entry_2664", buf.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_21.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_21.java new file mode 100644 index 0000000000..6272a188a3 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_21.java @@ -0,0 +1,51 @@ +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_21 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + + String sql = "select `a_entry`.`id` from `a_entry`"; + + 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(0, parameters.size()); + + StringBuilder buf = new StringBuilder(); + SQLASTOutputVisitor visitor1 = SQLUtils.createOutputVisitor(buf, dbType); + visitor1.addTableMapping("a_entry", "a_entry_2664"); + visitor1.setParameters(visitor.getParameters()); + stmt.accept(visitor1); + + assertEquals("SELECT a_entry_2664.`id`\n" + + "FROM a_entry_2664", buf.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_22.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_22.java new file mode 100644 index 0000000000..7cc9c2c5a9 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_22.java @@ -0,0 +1,91 @@ +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_22 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + + String sql = "/* 0bba613214845441110397435e/0.4.6.25// */select `f`.`id`,`f`.`biz_id`,`f`.`user_id`,`f`.`file_name`,`f`.`parent_id`,`f`.`length`,`f`.`type`,`f`.`stream_key`,`f`.`biz_status`,`f`.`mark`,`f`.`content_modified`,`f`.`status`,`f`.`gmt_create`,`f`.`gmt_modified`,`f`.`md5`,`f`.`extra_str1`,`f`.`extra_str2`,`f`.`extra_str3`,`f`.`extra_num1`,`f`.`extra_num2`,`f`.`extra_num3`,`f`.`safe`,`f`.`open_status`,`f`.`inner_mark`,`f`.`sys_extra`,`f`.`feature`,`f`.`domain_option`,`f`.`version`,`f`.`reference_type`,`f`.`dentry_type`,`f`.`space_id`,`f`.`extension`,`f`.`creator_id`,`f`.`modifier_id`,`f`.`store_type`,`f`.`link_mark`,`f`.`content_type` from ( select `vfs_dentry_2664`.`id` from `vfs_dentry_2664` FORCE INDEX (idx_gmt) where ((`vfs_dentry_2664`.`extra_str1` = '97d45a25df387b4460e5b4151daeb452') AND (`vfs_dentry_2664`.`biz_id` = 62) AND (`vfs_dentry_2664`.`status` = 0) AND (`vfs_dentry_2664`.`user_id` = '11168360') AND (`vfs_dentry_2664`.`dentry_type` = 1)) limit 0,50 ) `t` join `vfs_dentry_2664` `f` on `t`.`id` = `f`.`id` where ((`t`.`id` = `f`.`id`) AND (`f`.`user_id` = 11168360))"; + + String psql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + assertEquals("SELECT `f`.`id`, `f`.`biz_id`, `f`.`user_id`, `f`.`file_name`, `f`.`parent_id`\n" + + "\t, `f`.`length`, `f`.`type`, `f`.`stream_key`, `f`.`biz_status`, `f`.`mark`\n" + + "\t, `f`.`content_modified`, `f`.`status`, `f`.`gmt_create`, `f`.`gmt_modified`, `f`.`md5`\n" + + "\t, `f`.`extra_str1`, `f`.`extra_str2`, `f`.`extra_str3`, `f`.`extra_num1`, `f`.`extra_num2`\n" + + "\t, `f`.`extra_num3`, `f`.`safe`, `f`.`open_status`, `f`.`inner_mark`, `f`.`sys_extra`\n" + + "\t, `f`.`feature`, `f`.`domain_option`, `f`.`version`, `f`.`reference_type`, `f`.`dentry_type`\n" + + "\t, `f`.`space_id`, `f`.`extension`, `f`.`creator_id`, `f`.`modifier_id`, `f`.`store_type`\n" + + "\t, `f`.`link_mark`, `f`.`content_type`\n" + + "FROM (SELECT vfs_dentry.`id`\n" + + "\tFROM vfs_dentry FORCE INDEX (idx_gmt)\n" + + "\tWHERE vfs_dentry.`extra_str1` = ?\n" + + "\t\tAND vfs_dentry.`biz_id` = ?\n" + + "\t\tAND vfs_dentry.`status` = ?\n" + + "\t\tAND vfs_dentry.`user_id` = ?\n" + + "\t\tAND vfs_dentry.`dentry_type` = ?\n" + + "\tLIMIT ?, ?\n" + + "\t) `t`\n" + + "\tJOIN vfs_dentry `f` ON `t`.`id` = `f`.`id`\n" + + "WHERE `t`.`id` = `f`.`id`\n" + + "\tAND `f`.`user_id` = ?", psql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(psql, 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(0, parameters.size()); + + StringBuilder buf = new StringBuilder(); + SQLASTOutputVisitor visitor1 = SQLUtils.createOutputVisitor(buf, dbType); + visitor1.addTableMapping("vfs_dentry", "vfs_dentry_001"); + visitor1.setParameters(visitor.getParameters()); + stmt.accept(visitor1); + + assertEquals("SELECT `f`.`id`, `f`.`biz_id`, `f`.`user_id`, `f`.`file_name`, `f`.`parent_id`\n" + + "\t, `f`.`length`, `f`.`type`, `f`.`stream_key`, `f`.`biz_status`, `f`.`mark`\n" + + "\t, `f`.`content_modified`, `f`.`status`, `f`.`gmt_create`, `f`.`gmt_modified`, `f`.`md5`\n" + + "\t, `f`.`extra_str1`, `f`.`extra_str2`, `f`.`extra_str3`, `f`.`extra_num1`, `f`.`extra_num2`\n" + + "\t, `f`.`extra_num3`, `f`.`safe`, `f`.`open_status`, `f`.`inner_mark`, `f`.`sys_extra`\n" + + "\t, `f`.`feature`, `f`.`domain_option`, `f`.`version`, `f`.`reference_type`, `f`.`dentry_type`\n" + + "\t, `f`.`space_id`, `f`.`extension`, `f`.`creator_id`, `f`.`modifier_id`, `f`.`store_type`\n" + + "\t, `f`.`link_mark`, `f`.`content_type`\n" + + "FROM (SELECT vfs_dentry_001.`id`\n" + + "\tFROM vfs_dentry_001 FORCE INDEX (idx_gmt)\n" + + "\tWHERE vfs_dentry_001.`extra_str1` = ?\n" + + "\t\tAND vfs_dentry_001.`biz_id` = ?\n" + + "\t\tAND vfs_dentry_001.`status` = ?\n" + + "\t\tAND vfs_dentry_001.`user_id` = ?\n" + + "\t\tAND vfs_dentry_001.`dentry_type` = ?\n" + + "\tLIMIT ?, ?\n" + + "\t) `t`\n" + + "\tJOIN vfs_dentry_001 `f` ON `t`.`id` = `f`.`id`\n" + + "WHERE `t`.`id` = `f`.`id`\n" + + "\tAND `f`.`user_id` = ?", buf.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/ParseUtil.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/ParseUtil.java new file mode 100644 index 0000000000..6f25485577 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/ParseUtil.java @@ -0,0 +1,206 @@ +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.ast.statement.*; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.google.common.collect.Lists; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Created by yunning on 16/6/3. + */ +public class ParseUtil { + + private final static String DML_REGEX = "^(\\s)*(SELECT|INSERT|UPDATE|DELETE)"; + private final static Pattern DML_PATTERN = Pattern.compile(DML_REGEX, Pattern.CASE_INSENSITIVE); //忽略大小写 + private final static String IP_REGEX = "^(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$"; + private final static Pattern IP_PATTERN = Pattern.compile(IP_REGEX, Pattern.CASE_INSENSITIVE); + private static Logger logger = Logger.getLogger(ParseUtil.class); + + public static boolean isDmlSQL(String querySql) { + return DML_PATTERN.matcher(querySql).find(); + } + + public static boolean isDmlSQL(SQLStatement statement /*String querySql*/) { + // return DML_1_PATTERN.matcher(querySql).find() || DML_2_PATTERN.matcher(querySql).find(); + return statement instanceof SQLSelectStatement || + statement instanceof SQLInsertStatement || + statement instanceof MySqlReplaceStatement || + statement instanceof SQLUpdateStatement || + statement instanceof SQLDeleteStatement; + } + + public static void main(String[] args) { + // String sql = "alter table sql_perf add index `idx_instance_8` (`host`,`port`,`hashcode`,`item`,`time`,`value`);"; + /* String sql = "CREATE INDEX PersonIndex\n" + + "ON Person (LastName) ";*/ + // String sql = "CREATE TABLE t (id int );"; + // String sql = "ALTER TABLE `app_api_dup_control`\n\tDROP INDEX `idx_url_uuid`,\n\tADD UNIQUE KEY `uk_url_uuid` (uuid, url)"; + /* String sql = "ALTER TABLE `push_seed_0000`\n" + + "\tADD KEY `idx_betstatus_gmtcreate` (bet_status, gmt_create),\n" + + "\tADD KEY `idx_winstatus_gmtcreate` (win_status, gmt_create)";*/ + // System.out.println(getIdxInfo(sql, "AA", null)); + + // System.out.println(DateTimeUtils.toYyyyMMddhhmmss(new Date())); + /*String ip = "xx"; + System.out.println(IP_PATTERN.matcher(ip).find());*/ + /* String sql = "\nalter table `dms_sign_info_0222` modify column `station_id` bigint comment '分拣流水中记录的分拨中心ID'"; + + List list = getIdxInfo(sql,"XX",null); + System.out.println(list);*/ + // String sql = "select * from task where status = 1 and valid = 1 and type <> 100 and type <> 99 order by priority desc,gmt_create limit 0,500"; + // System.out.println(parseSQL(sql)); + + /*String sql = "SELECT IFNULL(SUM(CASE WHEN `tms_waybill_detail`.`dissendout_status` = ? AND DATE_ADD(`tms_waybill_detail`.`rdc_accept_time`, INTERVAL ? HOUR) < `tms_waybill_detail`.`dissendout_time` OR `tms_waybill_detail`.`dissendout_status` = ? AND DATE_ADD(`tms_waybill_detail`.`rdc_accept_time`, INTERVAL ? HOUR) < NOW() THEN ? ELSE ? END), ?) AS `count` FROM tms_waybill_detail `tms_waybill_detail` WHERE `tms_waybill_detail`.`rdc_accept_time` >= ? AND `tms_waybill_detail`.`rdc_accept_time` < ? AND `tms_waybill_detail`.`districenter_code` = ? AND `tms_waybill_detail`.`schedule_code` = ?"; + + String table = "[\"tms_waybill_detail_0014\"]"; + String params = "[1,24,0,24,1,0,0,\"2017-01-15 00:00:00\",\"2017-01-15 17:32:03.558\",686,\"10102\"]"; + + System.out.println("----- : "+restore(sql,table,params));*/ + + String sql = "/* 0bba613214845441110397435e/0.4.6.25// */select `f`.`id`,`f`.`biz_id`,`f`.`user_id`,`f`.`file_name`,`f`.`parent_id`,`f`.`length`,`f`.`type`,`f`.`stream_key`,`f`.`biz_status`,`f`.`mark`,`f`.`content_modified`,`f`.`status`,`f`.`gmt_create`,`f`.`gmt_modified`,`f`.`md5`,`f`.`extra_str1`,`f`.`extra_str2`,`f`.`extra_str3`,`f`.`extra_num1`,`f`.`extra_num2`,`f`.`extra_num3`,`f`.`safe`,`f`.`open_status`,`f`.`inner_mark`,`f`.`sys_extra`,`f`.`feature`,`f`.`domain_option`,`f`.`version`,`f`.`reference_type`,`f`.`dentry_type`,`f`.`space_id`,`f`.`extension`,`f`.`creator_id`,`f`.`modifier_id`,`f`.`store_type`,`f`.`link_mark`,`f`.`content_type` from ( select `vfs_dentry_2664`.`id` from `vfs_dentry_2664` FORCE INDEX (idx_gmt) where ((`vfs_dentry_2664`.`extra_str1` = '97d45a25df387b4460e5b4151daeb452') AND (`vfs_dentry_2664`.`biz_id` = 62) AND (`vfs_dentry_2664`.`status` = 0) AND (`vfs_dentry_2664`.`user_id` = '11168360') AND (`vfs_dentry_2664`.`dentry_type` = 1)) limit 0,50 ) `t` join `vfs_dentry_2664` `f` on `t`.`id` = `f`.`id` where ((`t`.`id` = `f`.`id`) AND (`f`.`user_id` = 11168360))"; + // SQLStatement sqlStatement = getStatement(sql); + + String sqlTempalte = parseSQL(sql); + JSONArray array = new JSONArray(); + array.add("VFS_DENTRY_001"); + System.out.println(restore(sqlTempalte,array.toJSONString(),new JSONArray().toJSONString())); + } + + public static boolean isIp(String host){ + return IP_PATTERN.matcher(host).find(); + } + + + + private static String filterChar(String name) { + if (StringUtils.isNotBlank(name)) { + String[] names = name.split("\\."); + StringBuilder nameSb = new StringBuilder(); + for (String n : names) { + if (n.startsWith("`") && n.endsWith("`")) { + nameSb.append(n.substring(1, n.length() - 1)).append("."); + } + } + return nameSb.substring(0, nameSb.length() - 1); + } + return name; + } + + public static String parseSQL(String sql) { + try { + final String dbType = JdbcConstants.MYSQL; + return ParameterizedOutputVisitorUtils.parameterize(sql, dbType).toUpperCase(); + } catch (Exception ex) { + logger.error("parser sql error : " + sql); + ex.printStackTrace(); + } + return null; + } + + public static String computeMD5Hex(String sqlTemplate) { + return DigestUtils.md5Hex(sqlTemplate).toUpperCase(); + } + + public static String restore(String sql, String table, String params/*JSONArray paramsArray, JSONArray destArray*/) { + JSONArray destArray = JSON.parseArray(table.replaceAll("''", "'")); + JSONArray paramsArray = JSON.parseArray(params.replaceAll("''", "'")); + String dbType = JdbcConstants.MYSQL; + List stmtList = SQLUtils.parseStatements(sql, dbType); + + SQLStatement stmt = stmtList.get(0); + + StringBuilder out = new StringBuilder(); + SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType); + List paramsList = Lists.newArrayList(paramsArray); + visitor.setParameters(paramsList); + + JSONArray srcArray = getSrcArray(sql); +/* + SchemaStatVisitor schemaStatVisitor = new MySqlSchemaStatVisitor(); + stmt.accept(schemaStatVisitor); + JSONArray srcArray = new JSONArray(); + for (Map.Entry entry : schemaStatVisitor.getTables().entrySet()) { + srcArray.add(entry.getKey().getName()); + }*/ + + for (int i = 0; i < srcArray.size(); i++) { + visitor.addTableMapping(srcArray.getString(i), destArray.getString(i)); + } + + stmt.accept(visitor); + + return out.toString(); + } + + private static JSONArray getSrcArray(String sql) { + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + SQLStatement stmt = stmtList.get(0); + 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); + stmt.accept(visitor); + String srcStr = JSONArray.toJSONString(visitor.getTables()); + return JSONArray.parseArray(srcStr); + } + + public static SQLStatement getStatement(String sql) { + try { + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + return stmtList.get(0); + } catch (Exception ex) { + logger.error("get statement error", ex); + } + return null; + } + + public static String getSqlHash(String sql) { + SQLStatement statement = getStatement(sql); + if (null == statement) return null; + return getSqlHash(statement); + } + + + public static String getSqlHash(SQLStatement statement) { + try { + + StringBuilder out = new StringBuilder(); + List parameters = new ArrayList(); + SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, JdbcConstants.MYSQL); + visitor.setParameterized(true); + visitor.setParameterizedMergeInList(true); + visitor.setParameters(parameters); + // visitor.setExportTables(true); + visitor.setPrettyFormat(false); + statement.accept(visitor); + + String sqlTemplate = out.toString(); + return DigestUtils.md5Hex(sqlTemplate); + } catch (Exception ex) { + logger.error("parseSql error ", ex); + } + return null; + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest.java index e51e1294fb..144d1ec85c 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest.java @@ -9,11 +9,11 @@ import junit.framework.TestCase; public class OdpsAlterTableDropPartitionTest extends TestCase { public void test_if() throws Exception { - String sql = "alter table sale_detail drop if not exists partition (sale_date='201312', region='hangzhou');"; + String sql = "alter table sale_detail drop if exists partition (sale_date='201312', region='hangzhou');"; Assert.assertEquals("ALTER TABLE sale_detail" // - + "\n\tDROP IF NOT EXISTS PARTITION (sale_date = '201312', region = 'hangzhou');", SQLUtils.formatOdps(sql)); + + "\n\tDROP IF EXISTS PARTITION (sale_date = '201312', region = 'hangzhou');", SQLUtils.formatOdps(sql)); Assert.assertEquals("alter table sale_detail" // - + "\n\tdrop if not exists partition (sale_date = '201312', region = 'hangzhou');", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + "\n\tdrop if exists partition (sale_date = '201312', region = 'hangzhou');", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); } public void test_purge() throws Exception { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest2.java new file mode 100644 index 0000000000..f96576dff3 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsAlterTableDropPartitionTest2.java @@ -0,0 +1,16 @@ +package com.alibaba.druid.bvt.sql.odps; + +import com.alibaba.druid.sql.SQLUtils; +import junit.framework.TestCase; +import org.junit.Assert; + +public class OdpsAlterTableDropPartitionTest2 extends TestCase { + + public void test_if() throws Exception { + String sql = "alter table myp.table2 drop if exists partition(ds=20161209) \n"; + Assert.assertEquals("ALTER TABLE myp.table2\n" + + "\tDROP IF EXISTS PARTITION (ds = 20161209)", SQLUtils.formatOdps(sql)); + Assert.assertEquals("alter table myp.table2\n" + + "\tdrop if exists partition (ds = 20161209)", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + } +}