From 9bd4b7a2b00e74f66283c24e6a01fd224e46a5d1 Mon Sep 17 00:00:00 2001 From: yakolee Date: Thu, 8 May 2014 17:21:11 +0800 Subject: [PATCH 01/13] improve sql parser --- .../mysql/visitor/MySqlOutputVisitor.java | 9 +++-- .../druid/sql/parser/SQLExprParser.java | 18 +++++----- .../bvt/sql/mysql/MySqlCreateTableTest.java | 33 +++++++++++++++++++ 3 files changed, 46 insertions(+), 14 deletions(-) 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 d4d9d6033f..d588612b26 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 @@ -383,11 +383,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (x.getCharSetName() != null) { print(" CHARACTER SET "); print(x.getCharSetName()); - - if (x.getCollate() != null) { - print(" COLLATE "); - print(x.getCollate()); - } + } + if (x.getCollate() != null) { + print(" COLLATE "); + print(x.getCollate()); } 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 c9c5e43e08..602162851c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1359,17 +1359,17 @@ public class SQLExprParser extends SQLParser { } charType.setCharSetName(lexer.stringVal()); lexer.nextToken(); + } + + if (lexer.token() == Token.IDENTIFIER) { + if (lexer.stringVal().equalsIgnoreCase("COLLATE")) { + lexer.nextToken(); - if (lexer.token() == Token.IDENTIFIER) { - if (lexer.stringVal().equalsIgnoreCase("COLLATE")) { - lexer.nextToken(); - - if (lexer.token() != Token.IDENTIFIER) { - throw new ParserException(); - } - charType.setCollate(lexer.stringVal()); - lexer.nextToken(); + if (lexer.token() != Token.IDENTIFIER) { + throw new ParserException(); } + charType.setCollate(lexer.stringVal()); + lexer.nextToken(); } } return charType; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java index b772a773f8..fbcb634cf5 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java @@ -53,4 +53,37 @@ public class MySqlCreateTableTest extends MysqlTest { // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "last_name"))); } + + + public void test_1() throws Exception { + String sql = "CREATE TABLE `ins_ebay_auth` (" + + " `auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id'," + + " `usr_id` int(10) NOT NULL COMMENT '外键,用户表'," + + " `status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效'," + + " `ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码'," + + " `ebay_name` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'eBay唯一名'," + + " `create_time` datetime NOT NULL COMMENT '授权时间', " + + " `invalid_time` datetime NOT NULL COMMENT '授权失效时间'," + + " PRIMARY KEY (`auth_id`)" + + " ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='INS_EBAY_AUTH';"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(7, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } } From a5c6636392f7a24b8d1a369771a609088a95765c Mon Sep 17 00:00:00 2001 From: yakolee Date: Thu, 8 May 2014 20:19:47 +0800 Subject: [PATCH 02/13] improve sql parser --- .../alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java | 2 +- .../com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index ec4b3de137..fa1154fa10 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -250,7 +250,7 @@ public class MySqlExprParser extends SQLExprParser { return primaryRest(expr); } - } else if ("COLLATE".equalsIgnoreCase(lexer.stringVal())) { + } else if ("COLLATE".equalsIgnoreCase(lexer.stringVal()) && !(expr instanceof SQLIdentifierExpr)) { lexer.nextToken(); if (lexer.token() != Token.IDENTIFIER) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java index fbcb634cf5..071c4c8de0 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest.java @@ -65,7 +65,7 @@ public class MySqlCreateTableTest extends MysqlTest { + " `create_time` datetime NOT NULL COMMENT '授权时间', " + " `invalid_time` datetime NOT NULL COMMENT '授权失效时间'," + " PRIMARY KEY (`auth_id`)" - + " ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='INS_EBAY_AUTH';"; + + " ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH'"; MySqlStatementParser parser = new MySqlStatementParser(sql); List statementList = parser.parseStatementList(); From 6fb3248603c493c4fc6f28af91bfbf05895abab2 Mon Sep 17 00:00:00 2001 From: yakolee Date: Thu, 15 May 2014 20:49:19 +0800 Subject: [PATCH 03/13] improve output visitor --- .../visitor/SQLServerParameterizedOutputVisitor.java | 9 +++++++++ .../sql/visitor/ParameterizedOutputVisitorUtils.java | 6 ++++++ .../alibaba/druid/sql/visitor/SQLASTOutputVisitor.java | 2 ++ 3 files changed, 17 insertions(+) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java index 2653ce3384..74a75774bc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; import com.alibaba.druid.sql.ast.expr.SQLNullExpr; import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; import com.alibaba.druid.sql.visitor.ParameterizedVisitor; @@ -90,5 +91,13 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor return ParameterizedOutputVisitorUtils.visit(this, x); } + + public boolean visit(SQLVariantRefExpr x) { + if (!ParameterizedOutputVisitorUtils.checkParameterize(x) || x.getName().equalsIgnoreCase("?")) { + return super.visit(x); + } + + return ParameterizedOutputVisitorUtils.visit(this, x); + } } 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 4a329c2a74..1c5560db36 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -189,6 +189,12 @@ public class ParameterizedOutputVisitorUtils { v.incrementReplaceCunt(); return false; } + + public static boolean visit(ParameterizedVisitor v, SQLVariantRefExpr x) { + v.print('?'); + v.incrementReplaceCunt(); + return false; + } public static SQLBinaryOpExpr merge(ParameterizedVisitor v, SQLBinaryOpExpr x) { SQLExpr left = x.getLeft(); 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 cae14c8ca4..d4dac9fd87 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -601,7 +601,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab decrementIndent(); } else if (parent instanceof ValuesClause) { println(); + print("("); x.getSubQuery().accept(this); + print(")"); println(); } else { print("("); From b1ed8db6a626269767229169dc379498e72a97ab Mon Sep 17 00:00:00 2001 From: yakolee Date: Fri, 16 May 2014 11:16:28 +0800 Subject: [PATCH 04/13] =?UTF-8?q?add=20logDiffrentThread=20=E5=BC=80?= =?UTF-8?q?=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alibaba/druid/pool/DruidDataSource.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 96190fb7a1..dc5655f2bc 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -149,6 +149,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public static ThreadLocal waitNanosLocal = new ThreadLocal(); + private boolean logDiffrentThread = true; + public DruidDataSource(){ this(false); } @@ -1128,7 +1130,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return; } - if (pooledConnection.getOwnerThread() != Thread.currentThread()) { + if (logDiffrentThread && pooledConnection.getOwnerThread() != Thread.currentThread()) { LOG.warn("get/close not same thread"); } @@ -2393,4 +2395,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return super.unwrap(iface); } + + public boolean isLogDiffrentThread() { + return logDiffrentThread; + } + + public void setLogDiffrentThread(boolean logDiffrentThread) { + this.logDiffrentThread = logDiffrentThread; + } } From 8f1a9b08ab4ac91e5a89ba2b44c1bbd761fb1f98 Mon Sep 17 00:00:00 2001 From: yakolee Date: Mon, 19 May 2014 16:17:31 +0800 Subject: [PATCH 05/13] improve MySqlParameterizedOutputVisitor --- .../MySqlParameterizedOutputVisitor.java | 9 ++++++ .../MySqlParameterizedOutputVisitorTest.java | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java index 68a3c04488..6d1a66f561 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java @@ -31,6 +31,7 @@ import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; import com.alibaba.druid.sql.visitor.ParameterizedVisitor; @@ -179,6 +180,14 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor implemen return ParameterizedOutputVisitorUtils.visit(this, x); } + + public boolean visit(MySqlCharExpr x) { + if (!ParameterizedOutputVisitorUtils.checkParameterize(x)) { + return super.visit(x); + } + + return ParameterizedOutputVisitorUtils.visit(this, x); + } protected void printValuesList(MySqlInsertStatement x) { List valuesList = x.getValuesList(); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java new file mode 100644 index 0000000000..1c6ae7247d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java @@ -0,0 +1,31 @@ +/* + * 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.visitor; + +import junit.framework.TestCase; + +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; + +public class MySqlParameterizedOutputVisitorTest extends TestCase { + + public void test_0() throws Exception { + String sql = "SELECT appsheetserialno FROM app_trans WHERE nodeid = _gbk '619' " + + " AND alino = _gbk '2013110900031031001700thfund00163619'" + + " AND apserialno = _gbk '201405120002300002170013205458'"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + } + +} From 7bfdd1cfea5da8123245d33e793f0127dac1e914 Mon Sep 17 00:00:00 2001 From: yakolee Date: Tue, 20 May 2014 20:03:24 +0800 Subject: [PATCH 06/13] improve ParameterizedOutputVisitor --- .../MySqlParameterizedOutputVisitor.java | 9 +++++ .../ParameterizedOutputVisitorUtils.java | 33 +++++++++++++++---- .../MySqlParameterizedOutputVisitorTest.java | 20 +++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java index 6d1a66f561..520327e6fa 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java @@ -22,6 +22,7 @@ import java.util.Properties; import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; @@ -181,6 +182,14 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor implemen return ParameterizedOutputVisitorUtils.visit(this, x); } + public boolean visit(SQLHexExpr x) { + if (!ParameterizedOutputVisitorUtils.checkParameterize(x)) { + return super.visit(x); + } + + return ParameterizedOutputVisitorUtils.visit(this, x); + } + public boolean visit(MySqlCharExpr x) { if (!ParameterizedOutputVisitorUtils.checkParameterize(x)) { return super.visit(x); 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 1c5560db36..7d97f2c721 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; @@ -55,11 +56,16 @@ public class ParameterizedOutputVisitorUtils { return sql; } - SQLStatement stmt = statementList.get(0); - StringBuilder out = new StringBuilder(); ParameterizedVisitor visitor = createParameterizedOutputVisitor(out, dbType); - stmt.accept(visitor); + + for (int i = 0; i < statementList.size(); i++) { + if (i > 0) { + out.append(";\n"); + } + SQLStatement stmt = statementList.get(i); + stmt.accept(visitor); + } if (visitor.getReplaceCount() == 0) { return sql; @@ -189,12 +195,18 @@ public class ParameterizedOutputVisitorUtils { v.incrementReplaceCunt(); return false; } - + public static boolean visit(ParameterizedVisitor v, SQLVariantRefExpr x) { v.print('?'); v.incrementReplaceCunt(); return false; } + + public static boolean visit(ParameterizedVisitor v, SQLHexExpr x) { + v.print('?'); + v.incrementReplaceCunt(); + return false; + } public static SQLBinaryOpExpr merge(ParameterizedVisitor v, SQLBinaryOpExpr x) { SQLExpr left = x.getLeft(); @@ -204,8 +216,17 @@ public class ParameterizedOutputVisitorUtils { if (left instanceof SQLLiteralExpr && right instanceof SQLLiteralExpr) { if (x.getOperator() == SQLBinaryOperator.Equality // || x.getOperator() == SQLBinaryOperator.NotEqual) { - left.putAttribute(ATTR_PARAMS_SKIP, true); - right.putAttribute(ATTR_PARAMS_SKIP, true); + if((left instanceof SQLIntegerExpr) && (right instanceof SQLIntegerExpr) ) { + if (((SQLIntegerExpr) left).getNumber().intValue() < 100) { + left.putAttribute(ATTR_PARAMS_SKIP, true); + } + if (((SQLIntegerExpr) right).getNumber().intValue() < 100) { + right.putAttribute(ATTR_PARAMS_SKIP, true); + } + } else { + left.putAttribute(ATTR_PARAMS_SKIP, true); + right.putAttribute(ATTR_PARAMS_SKIP, true); + } } return x; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java index 1c6ae7247d..8aa9b52bcc 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java @@ -26,6 +26,26 @@ public class MySqlParameterizedOutputVisitorTest extends TestCase { + " AND alino = _gbk '2013110900031031001700thfund00163619'" + " AND apserialno = _gbk '201405120002300002170013205458'"; System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); + + sql = "SELECT p.AppId, p.PlayerId, p.Nickname, p.CreateTime FROM acc_playeruser AS pu INNER JOIN acc_player AS p ON (pu.AppId = p.AppId AND pu.PlayerId = p.PlayerId) WHERE pu.UserId=x'881A58F6204D4E048F66E41596A66A57';"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); + + sql = "SET @now := NOW(); INSERT characters (uid, name, race, career, sex, creation) VALUES (4068548, '', 58, 0, 0, @now); SET @id := LAST_INSERT_ID(); INSERT characters_data (character_id, data, creation) VALUES (@id, ' \0\0\0\0\0\0\0\04068548\0\0\0:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0__\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', @now); SELECT @id; "; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); + + sql = "INSERT INTO qrtz_JOB_DETAILS (SCHED_NAME, JOB_NAME, JOB_GROUP, DESCRIPTION, JOB_CLASS_NAME, IS_DURABLE, IS_NONCONCURRENT, IS_UPDATE_DATA, REQUESTS_RECOVERY, JOB_DATA) VALUES('DefaultQuartzScheduler', 'taobao.item.recommend.delete_368815794_2_35391685928', 'tasks', null, 'cn.agooo.job.TasksJob', 0, 0, 0, 0, x'ACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000017400077461736B7349647372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000002063227800')"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); + + sql = "SELECT * FROM sync_contactsdata WHERE __id=x'2EEE5AE7CB0E4AF697D966AE8BF046B8'"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); + + sql = "select TID,POSTFEE,RECEIVERADDRESS from tradegroup003 where (0 = 650954981082695 or tid=650954981082695) And SELLERNICK='______________' And BUYERNICK='yingge7' and CREATED > date_sub(now(), interval 48 hour) and STATUS = 'WAIT_BUYER_PAY' and func_isNotFollowgroup003(tradegroup003.tid,'______________') = 0"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); } } From 52b66266d8f2596c567597c9d501a3ba7592abc8 Mon Sep 17 00:00:00 2001 From: yakolee Date: Wed, 21 May 2014 14:49:49 +0800 Subject: [PATCH 07/13] improve ParameterizedOutputVisitor --- .../druid/sql/dialect/mysql/parser/MySqlLexer.java | 3 +++ .../alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java | 2 ++ .../druid/sql/dialect/oracle/parser/OracleLexer.java | 2 ++ .../sql/dialect/sqlserver/parser/SQLServerLexer.java | 2 ++ src/main/java/com/alibaba/druid/sql/parser/Lexer.java | 8 ++++++++ .../sql/visitor/ParameterizedOutputVisitorUtils.java | 2 +- .../visitor/MySqlParameterizedOutputVisitorTest.java | 5 +++++ 7 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java index 9944ab2acd..8371dbe9bf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java @@ -105,6 +105,7 @@ public class MySqlLexer extends Lexer { stringVal = subString(mark, bufPos); token = Token.LINE_COMMENT; + hasComment = true; if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { return; @@ -440,6 +441,7 @@ public class MySqlLexer extends Lexer { } else { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; + hasComment = true; } if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { @@ -481,6 +483,7 @@ public class MySqlLexer extends Lexer { stringVal = subString(mark, bufPos + 1); token = Token.LINE_COMMENT; + hasComment = true; if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { return; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java index eaf42c112f..68f179def7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java @@ -92,6 +92,7 @@ public class OdpsLexer extends Lexer { } else { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; + hasComment = true; } if (token != Token.HINT && !isAllowComment()) { @@ -134,6 +135,7 @@ public class OdpsLexer extends Lexer { stringVal = subString(mark + 1, bufPos); token = Token.LINE_COMMENT; + hasComment = true; return; } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 3d3f6321ca..2352d2fdfb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -230,6 +230,7 @@ public class OracleLexer extends Lexer { } else { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; + hasComment = true; } if (token != Token.HINT && !isAllowComment()) { @@ -272,6 +273,7 @@ public class OracleLexer extends Lexer { stringVal = subString(mark + 1, bufPos); token = Token.LINE_COMMENT; + hasComment = true; return; } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java index aab7796ba8..84abe762fd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java @@ -100,6 +100,7 @@ public class SQLServerLexer extends Lexer { } else { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; + hasComment = true; } if (token != Token.HINT && !isAllowComment()) { @@ -142,6 +143,7 @@ public class SQLServerLexer extends Lexer { stringVal = subString(mark + 1, bufPos); token = Token.LINE_COMMENT; + hasComment = true; return; } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index f9032f994b..a8174a78eb 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -69,6 +69,8 @@ public class Lexer { private int varIndex = -1; protected CommentHandler commentHandler; + + protected boolean hasComment = false; public Lexer(String input){ this(input, true); @@ -747,6 +749,7 @@ public class Lexer { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; + hasComment = true; return; } @@ -777,6 +780,7 @@ public class Lexer { stringVal = subString(mark + 1, bufPos); token = Token.LINE_COMMENT; + hasComment = true; return; } } @@ -1045,4 +1049,8 @@ public class Lexer { boolean handle(Token lastToken, String comment); } + + public boolean isHasComment() { + return hasComment; + } } 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 7d97f2c721..9f0e35a1c1 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -67,7 +67,7 @@ public class ParameterizedOutputVisitorUtils { stmt.accept(visitor); } - if (visitor.getReplaceCount() == 0) { + if (visitor.getReplaceCount() == 0 && !parser.getLexer().isHasComment()) { return sql; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java index 8aa9b52bcc..acd5916e50 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java @@ -46,6 +46,11 @@ public class MySqlParameterizedOutputVisitorTest extends TestCase { sql = "select TID,POSTFEE,RECEIVERADDRESS from tradegroup003 where (0 = 650954981082695 or tid=650954981082695) And SELLERNICK='______________' And BUYERNICK='yingge7' and CREATED > date_sub(now(), interval 48 hour) and STATUS = 'WAIT_BUYER_PAY' and func_isNotFollowgroup003(tradegroup003.tid,'______________') = 0"; System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); + + sql ="SHOW COLUMNS FROM `pms_purchase_ops`/*20140512152820##%2Fbase.php%3Fshopid%3D%26module%3Dpms%26action%3DqualityItem%26op_id%3D756%26params%3Dcase%253Aupdate%252Ctable%253Aquality%252Corder_id%253A201405090006DL%252Creceive_no%253AQCI01201405090006DL%252Creceive_treat%253AALL_DONE%260.5652460628381133*/;"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); + System.out.println("-----------------------"); } } From a2c84319102253676d099d40f2158e079199dadf Mon Sep 17 00:00:00 2001 From: yakolee Date: Fri, 23 May 2014 14:00:12 +0800 Subject: [PATCH 08/13] improve ParameterizedOutputVisitor --- .../mysql/visitor/MySqlOutputVisitor.java | 2 +- .../sql/visitor/SQLASTOutputVisitor.java | 22 +++++++++++++++++++ .../MySqlParameterizedOutputVisitorTest.java | 19 ++++++++++++++-- 3 files changed, 40 insertions(+), 3 deletions(-) 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 d588612b26..3fc53a8b7c 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 @@ -171,7 +171,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV return visit((MySqlSelectQueryBlock) select); } - return false; + return super.visit(select); } public boolean visit(MySqlSelectQueryBlock x) { 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 d4dac9fd87..42d35200d3 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -97,6 +97,7 @@ import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEvent; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType; +import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropDatabaseStatement; import com.alibaba.druid.sql.ast.statement.SQLDropFunctionStatement; @@ -1413,6 +1414,27 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab x.getName().accept(this); return false; } + + @Override + public boolean visit(SQLCreateViewStatement x) { + print("CREATE "); + if(x.isOrReplace()) { + print("OR REPLACE "); + } + print("VIEW "); + x.getName().accept(this); + + if (x.getColumns().size() > 0) { + print(" ("); + printAndAccept(x.getColumns(), ", "); + print(")"); + } + + print(" AS "); + + x.getSubQuery().accept(this); + return false; + } @Override public boolean visit(SQLAlterTableDropIndex x) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java index acd5916e50..9dee025bc8 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlParameterizedOutputVisitorTest.java @@ -18,6 +18,7 @@ package com.alibaba.druid.bvt.sql.mysql.visitor; import junit.framework.TestCase; import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.util.JdbcConstants; public class MySqlParameterizedOutputVisitorTest extends TestCase { @@ -47,10 +48,24 @@ public class MySqlParameterizedOutputVisitorTest extends TestCase { sql = "select TID,POSTFEE,RECEIVERADDRESS from tradegroup003 where (0 = 650954981082695 or tid=650954981082695) And SELLERNICK='______________' And BUYERNICK='yingge7' and CREATED > date_sub(now(), interval 48 hour) and STATUS = 'WAIT_BUYER_PAY' and func_isNotFollowgroup003(tradegroup003.tid,'______________') = 0"; System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); System.out.println("-----------------------"); - - sql ="SHOW COLUMNS FROM `pms_purchase_ops`/*20140512152820##%2Fbase.php%3Fshopid%3D%26module%3Dpms%26action%3DqualityItem%26op_id%3D756%26params%3Dcase%253Aupdate%252Ctable%253Aquality%252Corder_id%253A201405090006DL%252Creceive_no%253AQCI01201405090006DL%252Creceive_treat%253AALL_DONE%260.5652460628381133*/;"; + + sql = "SHOW COLUMNS FROM `pms_purchase_ops`/*20140512152820##%2Fbase.php%3Fshopid%3D%26module%3Dpms%26action%3DqualityItem%26op_id%3D756%26params%3Dcase%253Aupdate%252Ctable%253Aquality%252Corder_id%253A201405090006DL%252Creceive_no%253AQCI01201405090006DL%252Creceive_treat%253AALL_DONE%260.5652460628381133*/;"; System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, "mysql")); System.out.println("-----------------------"); } + public void test_1() throws Exception { + String sql = "create or replace view vtmp_log_node_204180 as select `twf_log_group_user`.`uni_id` as `user_id`, `twf_log_group_user`.`control_group_type` from `twf_log_group_user` where `twf_log_group_user`.`subjob_id` = 204180"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL)); + System.out.println("-----------------------"); + + sql = " create view V_CustomerGoodsNf as select a.*,b.GoodsNO,b.GoodsName,b.SpecName,c.CustomerName,c.NickName,c.Tel,c.Email, StatusExt = (CASE a.curStatus WHEN (0) THEN ('待通知') WHEN (1) THEN ('已通知') WHEN (2) THEN ('已过期') WHEN (3) THEN ('被取消')END) from G_Customer_GoodsNotify a left outer join V_GoodsListBySpec b on a.GoodsID=b.GoodsID and a.SpecID=b.SpecID left outer join G_Customer_CustomerList c on a.CustomerID=c.CustomerID"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.SQL_SERVER)); + System.out.println("-----------------------"); + + sql = "CREATE view V_API_GoodsMatch as SELECT a.SpecName, a.GoodsNO, a.GoodsName, bMatch = CONVERT(bit, (CASE isnull(b.Numiid, '') WHEN ('') THEN (0) ELSE (1) END)), issys1 = (CASE isnull(b.issys, '') WHEN ('') THEN ('无') WHEN (0) THEN ('未同步') WHEN (1) THEN ('待同步') WHEN (2) THEN ('同步失败') WHEN (3) THEN ('同步成功') END), bFixNum = isnull(b.bFixNum, 0), bVirNum = isnull(b.bVirNum, 0), issys = isnull(b.issys, 0), FixNum = isnull(b.FixNum, 0), VirNumBase = isnull(b.VirNumBase, 0), VirNumInc = isnull(b.VirNumInc, 0), b.TBName, b.TBSku, b.UpdateTime, b.syscount, b.sysLog, c.ShopName, b.TBOuterID, b.SKUOuterID, d .FlagName, b.GoodsID, b.SpecID, b.Numiid, b.Skuid, b.BTBGoods, b.sysGoodsType, b.ID, bstop = CONVERT(bit, isnull(b.bstop, 0)), b.bSingletb, b.SingleNumPer, b.VirNumTop, isnull(b.goodstype, '0') AS goodstype, CASE b.SpecID WHEN - 2 THEN 1 ELSE 0 END AS pcbs FROM V_GoodsSpec a LEFT OUTER JOIN G_API_SysMatch b ON a.GoodsID = b.GoodsID AND CASE b.SpecID WHEN - 2 THEN 1 ELSE a.specid END = CASE b.SpecID WHEN - 2 THEN 1 ELSE b.SpecID END AND b.GoodsType = 0 LEFT OUTER JOIN G_Cfg_ShopList c ON b.ShopID = c.ShopID LEFT OUTER JOIN dbo.G_Cfg_RecordFlag d ON a.FlagID = d .FlagID UNION ALL SELECT '' AS SpecName, a.GoodsNO, a.GoodsName, bMatch = CONVERT(bit, (CASE isnull(b.Numiid, '') WHEN ('') THEN (0) ELSE (1) END)), issys1 = (CASE isnull(b.issys, '') WHEN ('') THEN ('无') WHEN (0) THEN ('未同步') WHEN (1) THEN ('待同步') WHEN (2) THEN ('同步失败') WHEN (3) THEN ('同步成功') END), bFixNum = isnull(b.bFixNum, 0), bVirNum = isnull(b.bVirNum, 0), issys = isnull(b.issys, 0), FixNum = isnull(b.FixNum, 0), VirNumBase = isnull(b.VirNumBase, 0), VirNumInc = isnull(b.VirNumInc, 0), b.TBName, b.TBSku, b.UpdateTime, b.syscount, b.sysLog, c.ShopName, b.TBOuterID, b.SKUOuterID, '' AS FlagName, b.GoodsID, b.SpecID, b.Numiid, b.Skuid, b.BTBGoods, b.sysGoodsType, b.ID, bstop = CONVERT(bit, isnull(b.bstop, 0)), b.bSingletb, b.SingleNumPer, b.VirNumTop, b.goodstype, 0 AS pcbs FROM g_goods_goodslistfit a LEFT OUTER JOIN g_api_sysma"; + System.out.println(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.SQL_SERVER)); + System.out.println("-----------------------"); + } + } From 6e11d7bc23a397bc884a1f80b4ba7fc272b4127c Mon Sep 17 00:00:00 2001 From: yakolee Date: Mon, 26 May 2014 16:36:22 +0800 Subject: [PATCH 09/13] bugfix for sql Eval --- .../sql/visitor/SQLEvalVisitorUtils.java | 89 +++++++++++++++++-- .../bvt/sql/eval/SQLEvalVisitorUtilsTest.java | 7 ++ 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index 10e5359333..54f2b39b41 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -1273,6 +1273,49 @@ public class SQLEvalVisitorUtils { return BigInteger.valueOf(((Number) val).longValue()); } + + public static Number castToNumber(String val) { + if (val == null) { + return null; + } + + try { + return Byte.parseByte(val); + } catch (NumberFormatException e) { + } + + try { + return Short.parseShort(val); + } catch (NumberFormatException e) { + } + + try { + return Integer.parseInt(val); + } catch (NumberFormatException e) { + } + + try { + return Long.parseLong(val); + } catch (NumberFormatException e) { + } + + try { + return Float.parseFloat(val); + } catch (NumberFormatException e) { + } + + try { + return Double.parseDouble(val); + } catch (NumberFormatException e) { + } + + try { + return new BigInteger(val); + } catch (NumberFormatException e) { + } + + return new BigDecimal(val); + } public static Date castToDate(Object val) { if (val == null) { @@ -1378,6 +1421,14 @@ public class SQLEvalVisitorUtils { if (a == null || b == null) { return null; } + + if (a instanceof String) { + a = castToNumber((String) a); + } + + if (b instanceof String) { + b = castToNumber((String) b); + } if (a instanceof BigDecimal || b instanceof BigDecimal) { BigDecimal decimalA = castToDecimal(a); @@ -1655,6 +1706,14 @@ public class SQLEvalVisitorUtils { if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) { return EVAL_VALUE_NULL; } + + if (a instanceof String && !(b instanceof String)) { + a = castToNumber((String) a); + } + + if (b instanceof String && !(a instanceof String)) { + b = castToNumber((String) b); + } if (a instanceof BigDecimal || b instanceof BigDecimal) { return castToDecimal(a).add(castToDecimal(b)); @@ -1695,7 +1754,7 @@ public class SQLEvalVisitorUtils { return castToByte(a) + castToByte(b); } - if (a instanceof String || b instanceof String) { + if (a instanceof String && b instanceof String) { return castToString(a) + castToString(b); } @@ -1718,6 +1777,14 @@ public class SQLEvalVisitorUtils { if (a instanceof Date || b instanceof Date) { return SQLEvalVisitor.EVAL_ERROR; } + + if (a instanceof String) { + a = castToNumber((String) a); + } + + if (b instanceof String) { + b = castToNumber((String) b); + } if (a instanceof BigDecimal || b instanceof BigDecimal) { return castToDecimal(a).subtract(castToDecimal(b)); @@ -1758,10 +1825,6 @@ public class SQLEvalVisitorUtils { return castToByte(a) - castToByte(b); } - if (a instanceof String && b instanceof String) { - return castToLong(a) - castToLong(b); - } - // return SQLEvalVisitor.EVAL_ERROR; throw new IllegalArgumentException(a.getClass() + " and " + b.getClass() + " not supported."); } @@ -1771,6 +1834,14 @@ public class SQLEvalVisitorUtils { return null; } + if (a instanceof String) { + a = castToNumber((String) a); + } + + if (b instanceof String) { + b = castToNumber((String) b); + } + if (a instanceof BigDecimal || b instanceof BigDecimal) { return castToDecimal(a).multiply(castToDecimal(b)); } @@ -1778,6 +1849,14 @@ public class SQLEvalVisitorUtils { if (a instanceof BigInteger || b instanceof BigInteger) { return castToBigInteger(a).multiply(castToBigInteger(b)); } + + if (a instanceof Double || b instanceof Double) { + return castToDouble(a) * castToDouble(b); + } + + if (a instanceof Float || b instanceof Float) { + return castToFloat(a) * castToFloat(b); + } if (a instanceof Long || b instanceof Long) { return castToLong(a) * castToLong(b); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java index 9c5e1c59e1..66fe661d09 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java @@ -29,6 +29,13 @@ public class SQLEvalVisitorUtilsTest extends TestCase { Assert.assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? - ?", Arrays. asList(2, 3))); Assert.assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? / ?", Arrays. asList(6, 3))); } + + public void test_evalExpr_3() throws Exception { + Assert.assertEquals(5.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? + ?", "2.0", 3)); + Assert.assertEquals(6.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? * ?", "2.0", 3)); + Assert.assertEquals(-1.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? - ?", "2.0", 3)); + Assert.assertEquals(2.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? / ?", "6.0", 3)); + } public void test_add() throws Exception { Assert.assertEquals(5, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? + ?", Arrays. asList(2, 3))); From 2d231cb6f9754f038e3bb195b6305f777cc5ef66 Mon Sep 17 00:00:00 2001 From: yakolee Date: Tue, 27 May 2014 16:58:34 +0800 Subject: [PATCH 10/13] bugfix --- .../sql/dialect/mysql/parser/MySqlExprParser.java | 2 +- .../dialect/oracle/visitor/OracleOutputVisitor.java | 3 +++ .../com/alibaba/druid/bvt/sql/mysql/SQLUtilsTest.java | 11 +++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index fa1154fa10..13f495ebcf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -234,7 +234,7 @@ public class MySqlExprParser extends SQLExprParser { String chars = lexer.stringVal(); concat.addParameter(new SQLCharExpr(chars)); lexer.nextToken(); - } while (lexer.token() == Token.LITERAL_CHARS); + } while (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS); expr = concat; } } else if (lexer.token() == Token.IDENTIFIER) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 1cc7c7c279..aa357e8155 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -2205,6 +2205,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS item.setParent(x); item.accept(this); } + print(";"); decrementIndent(); return false; @@ -2226,6 +2227,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS item.setParent(x); item.accept(this); } + print(";"); decrementIndent(); return false; @@ -2256,6 +2258,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS println(); } } + print(";"); decrementIndent(); for (ElseIf elseIf : x.getElseIfList()) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsTest.java index a376d3b0a6..430bca6bfc 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsTest.java @@ -18,4 +18,15 @@ public class SQLUtilsTest extends TestCase { "\nFROM t" + // "\nWHERE id = 'abc'", formattedSql); } + + public void test_format_1() throws Exception { + String sql = "select * from t where tname LIKE \"%\"'温'\"%\""; + String formattedSql = SQLUtils.formatMySql(sql); + Assert.assertEquals("SELECT *\nFROM t\nWHERE tname LIKE CONCAT('%', '温', '%')", formattedSql); + } + + public void test_format_2() throws Exception { + String sql = "begin\n" + " if (a=10) then\n" + " null;\n" + " else\n" + " null;\n" + " end if;\n" + "end;"; + System.out.println(SQLUtils.formatOracle(sql)); + } } From a9f290abf2bae9831d262b8977fe8a7c0c56bb71 Mon Sep 17 00:00:00 2001 From: yakolee Date: Wed, 28 May 2014 11:16:24 +0800 Subject: [PATCH 11/13] bugfix --- src/main/java/com/alibaba/druid/pool/DruidDataSource.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index dc5655f2bc..c5e11575ac 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1571,7 +1571,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat value.setTestWhileIdle(this.isTestWhileIdle()); value.setDefaultAutoCommit(this.isDefaultAutoCommit()); - value.setDefaultReadOnly(this.getDefaultReadOnly()); + if (getDefaultReadOnly() != null) { + value.setDefaultReadOnly(this.getDefaultReadOnly()); + } value.setDefaultTransactionIsolation(this.getDefaultTransactionIsolation()); value.setLogicConnectErrorCount(connectErrorCount.getAndSet(0)); From 47c76252472ac84097219876cb1dfeba3c4f85ec Mon Sep 17 00:00:00 2001 From: yakolee Date: Fri, 30 May 2014 16:38:39 +0800 Subject: [PATCH 12/13] bug fix --- .../dialect/mysql/parser/MySqlExprParser.java | 2 +- .../mysql/visitor/MySqlOutputVisitor.java | 5 --- .../druid/sql/parser/SQLExprParser.java | 10 ------ .../java/com/alibaba/druid/DruidTest.java | 36 ------------------- 4 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 src/test/java/com/alibaba/druid/DruidTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 3e03284208..c9d334b2d5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -250,7 +250,7 @@ public class MySqlExprParser extends SQLExprParser { return primaryRest(expr); } - } else if ("COLLATE".equalsIgnoreCase(lexer.stringVal()) && !(expr instanceof SQLIdentifierExpr)) { + } else if ("COLLATE".equalsIgnoreCase(lexer.stringVal())) { lexer.nextToken(); if (lexer.token() == Token.EQ) { 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 f18724700c..3fc53a8b7c 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 @@ -384,11 +384,6 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print(" CHARACTER SET "); print(x.getCharSetName()); } - if (x.getCollate() != null) { - print(" COLLATE "); - print(x.getCollate()); - } - if (x.getCollate() != null) { print(" COLLATE "); print(x.getCollate()); 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 e0be2fb7b7..602162851c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1371,17 +1371,7 @@ public class SQLExprParser extends SQLParser { charType.setCollate(lexer.stringVal()); lexer.nextToken(); } - }else if(identifierEquals("COLLATE")){ - lexer.nextToken(); - - if (lexer.token() != Token.IDENTIFIER) { - throw new ParserException(); - } - - charType.setCollate(lexer.stringVal()); - lexer.nextToken(); } - return charType; } diff --git a/src/test/java/com/alibaba/druid/DruidTest.java b/src/test/java/com/alibaba/druid/DruidTest.java deleted file mode 100644 index 13ae9d095c..0000000000 --- a/src/test/java/com/alibaba/druid/DruidTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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; - -import junit.framework.TestCase; - -import com.alibaba.druid.pool.DruidDataSource; - -public class DruidTest extends TestCase { - - public void test_0() throws Exception { - DruidDataSource ds = new DruidDataSource(); - ds.setMaxWait(30); - ds.setInitialSize(0); - ds.setUrl("jdbc:mysql:xxx"); - - try { - ds.getConnection(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } -} From 7a6e0d02190da3b9491a4133d68939124a4c6a65 Mon Sep 17 00:00:00 2001 From: "Wang,Tao" Date: Sat, 31 May 2014 16:28:43 +0800 Subject: [PATCH 13/13] Update DruidAbstractDataSource.java --- .../java/com/alibaba/druid/pool/DruidAbstractDataSource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 3e1b126513..80e1fa74ba 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -1177,7 +1177,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements String[] filterArray = filters.split("\\,"); for (String item : filterArray) { - FilterManager.loadFilter(this.filters, item); + FilterManager.loadFilter(this.filters, item.trim()); } }