From 21064d3d1ac5f427f31eca6f8010a5dbaba67063 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 22 Jun 2013 16:29:54 +0800 Subject: [PATCH 1/8] bug fixed for LogFilter --- .../druid/filter/logging/LogFilter.java | 37 +++++++++--- .../druid/bvt/filter/log/LogFilterTest4.java | 57 +++++++++++++++++++ 2 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest4.java diff --git a/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java b/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java index 745d1c334e..66a194a1f4 100644 --- a/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java +++ b/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java @@ -21,6 +21,7 @@ import java.sql.Savepoint; import java.sql.Types; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import com.alibaba.druid.filter.FilterChain; import com.alibaba.druid.filter.FilterEventAdapter; @@ -82,22 +83,40 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM protected DataSourceProxy dataSource; public LogFilter(){ + configFromProperties(System.getProperties()); + } + + public void configFromProperties(Properties properties) { { - String prop = System.getProperty("druid.log.stmt"); - if (prop == "false") { + String prop = properties.getProperty("druid.log.conn"); + if ("false".equals(prop)) { + connectionLogEnabled = false; + } else if ("true".equals(prop)) { + connectionLogEnabled = true; + } + } + { + String prop = properties.getProperty("druid.log.stmt"); + if ("false".equals(prop)) { statementLogEnabled = false; + } else if ("true".equals(prop)) { + statementLogEnabled = true; } } { - String prop = System.getProperty("druid.log.rs"); - if (prop == "false") { + String prop = properties.getProperty("druid.log.rs"); + if ("false".equals(prop)) { resultSetLogEnabled = false; + } else if ("true".equals(prop)) { + resultSetLogEnabled = true; } } { - String prop = System.getProperty("druid.log.stmt.executableSql"); - if (prop == "true") { + String prop = properties.getProperty("druid.log.stmt.executableSql"); + if ("true".equals(prop)) { statementExecutableSqlLogEnable = true; + } else if ("false".equals(prop)) { + statementExecutableSqlLogEnable = false; } } } @@ -306,7 +325,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM public void setStatementParameterSetLogEnabled(boolean statementParameterSetLogEnable) { this.statementParameterSetLogEnable = statementParameterSetLogEnable; } - + public boolean isStatementParameterClearLogEnable() { return isStatementLogEnabled() && statementParameterClearLogEnable; } @@ -737,7 +756,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM buf.append(stmtId(statement)); buf.append("}"); buf.append(" Parameters : ["); - + for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) { JdbcParameter parameter = statement.getParameter(i); if (i != 0) { @@ -746,7 +765,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM if (parameter == null) { continue; } - + int sqlType = parameter.getSqlType(); Object value = parameter.getValue(); switch (sqlType) { diff --git a/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest4.java b/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest4.java new file mode 100644 index 0000000000..9ca3d69677 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest4.java @@ -0,0 +1,57 @@ +package com.alibaba.druid.bvt.filter.log; + +import java.util.Properties; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.filter.logging.Log4jFilter; +import com.alibaba.druid.filter.logging.LogFilter; + +public class LogFilterTest4 extends TestCase { + + public void test_properties() throws Exception { + LogFilter filter = new Log4jFilter(); + + Assert.assertEquals(true, filter.isConnectionLogEnabled()); + Assert.assertEquals(true, filter.isStatementLogEnabled()); + Assert.assertEquals(false, filter.isStatementExecutableSqlLogEnable()); + Assert.assertEquals(true, filter.isResultSetLogEnabled()); + } + + public void test_properties_1() throws Exception { + + System.setProperty("druid.log.conn", "false"); + System.setProperty("druid.log.stmt", "false"); + System.setProperty("druid.log.rs", "false"); + System.setProperty("druid.log.stmt.executableSql", "true"); + + try { + LogFilter filter = new Log4jFilter(); + + Assert.assertEquals(false, filter.isConnectionLogEnabled()); + Assert.assertEquals(false, filter.isStatementLogEnabled()); + Assert.assertEquals(true, filter.isStatementExecutableSqlLogEnable()); + Assert.assertEquals(false, filter.isResultSetLogEnabled()); + + Properties properties = new Properties(); + properties.setProperty("druid.log.conn", "true"); + properties.setProperty("druid.log.stmt", "true"); + properties.setProperty("druid.log.rs", "true"); + properties.setProperty("druid.log.stmt.executableSql", "false"); + + filter.configFromProperties(properties); + + Assert.assertEquals(true, filter.isConnectionLogEnabled()); + Assert.assertEquals(true, filter.isStatementLogEnabled()); + Assert.assertEquals(false, filter.isStatementExecutableSqlLogEnable()); + Assert.assertEquals(true, filter.isResultSetLogEnabled()); + } finally { + System.clearProperty("druid.log.conn"); + System.clearProperty("druid.log.stmt"); + System.clearProperty("druid.log.rs"); + System.clearProperty("druid.log.stmt.executableSql"); + } + } +} From 9773119076355af79a18c07078bccb6ef61ef430 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 22 Jun 2013 16:30:50 +0800 Subject: [PATCH 2/8] 0.2.22-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f534b99eea..79afa814a4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.alibaba druid - 0.2.21 + 0.2.22-SNAPSHOT jar druid From fc75d7ab253d3c915fc661490e86cbf3aaa67d99 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 26 Jun 2013 23:20:57 +0800 Subject: [PATCH 3/8] bug fixed sql parser, support column name is 'comment' --- pom.xml | 6 +++--- .../java/com/alibaba/druid/sql/parser/SQLExprParser.java | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 79afa814a4..29d360b4d1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 4.11 true - true + true UTF-8 1.6 @@ -88,8 +88,8 @@ 3.0 UTF-8 - 1.6 - 1.6 + ${jdk.version} + ${jdk.version} 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 6b6f12a4ae..484e3101f4 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -226,6 +226,7 @@ public class SQLExprParser extends SQLParser { case COLUMN: case IF: case END: + case COMMENT: sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); break; From 29ab2b98edbb5895ebf908927aa38fc0a80ab8c1 Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 27 Jun 2013 23:41:04 +0800 Subject: [PATCH 4/8] DruidDataSource support mbean register & unregister --- .../druid/filter/config/ConfigFilter.java | 1 - .../alibaba/druid/pool/DruidDataSource.java | 26 +++++- .../alibaba/druid/bvt/pool/RegisterTest.java | 27 ++++++ .../java/com/alibaba/druid/pool/MemTest.java | 93 +++++++++---------- 4 files changed, 96 insertions(+), 51 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/RegisterTest.java diff --git a/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java b/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java index 58760be896..6f54d09769 100644 --- a/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java +++ b/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java @@ -279,7 +279,6 @@ public class ConfigFilter extends FilterAdapter { } } - @SuppressWarnings("resource") private InputStream getFileAsStream(String filePath) throws FileNotFoundException { InputStream inStream = null; File file = new File(filePath); diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index bd128cd05c..90d200717c 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -139,6 +139,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private boolean useGloalDataSourceStat = false; + private boolean mbeanRegistered = false; + public DruidDataSource(){ this(false); } @@ -614,8 +616,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat initedLatch.await(); initedTime = new Date(); - ObjectName objectName = DruidDataSourceStatManager.addDataSource(this, this.name); - this.setObjectName(objectName); + registerMbean(); if (connectError != null && poolingCount == 0) { throw connectError; @@ -1222,7 +1223,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } poolingCount = 0; - DruidDataSourceStatManager.removeDataSource(this); + unregisterMbean(); enable = false; notEmpty.signalAll(); @@ -1243,6 +1244,25 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } + public void registerMbean() { + if (!mbeanRegistered) { + ObjectName objectName = DruidDataSourceStatManager.addDataSource(this, this.name); + this.setObjectName(objectName); + this.mbeanRegistered = true; + } + } + + public void unregisterMbean() { + if (mbeanRegistered) { + DruidDataSourceStatManager.removeDataSource(this); + mbeanRegistered = false; + } + } + + public boolean isMbeanRegistered() { + return mbeanRegistered; + } + void putLast(DruidConnectionHolder e, long lastActiveTimeMillis) { e.setLastActiveTimeMillis(lastActiveTimeMillis); connections[poolingCount++] = e; diff --git a/src/test/java/com/alibaba/druid/bvt/pool/RegisterTest.java b/src/test/java/com/alibaba/druid/bvt/pool/RegisterTest.java new file mode 100644 index 0000000000..c8a811ba25 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/RegisterTest.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.bvt.pool; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.pool.DruidDataSource; + + +public class RegisterTest extends TestCase { + public void test() throws Exception { + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.init(); + + Assert.assertTrue(dataSource.isMbeanRegistered()); + + dataSource.registerMbean(); + Assert.assertTrue(dataSource.isMbeanRegistered()); + + dataSource.unregisterMbean(); + Assert.assertFalse(dataSource.isMbeanRegistered()); + Assert.assertFalse(dataSource.isMbeanRegistered()); + + dataSource.close(); + } +} diff --git a/src/test/java/com/alibaba/druid/pool/MemTest.java b/src/test/java/com/alibaba/druid/pool/MemTest.java index ee123fb9f7..cc70aed9e5 100644 --- a/src/test/java/com/alibaba/druid/pool/MemTest.java +++ b/src/test/java/com/alibaba/druid/pool/MemTest.java @@ -1,57 +1,56 @@ package com.alibaba.druid.pool; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.List; - -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 java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.PriorityQueue; +import java.util.Properties; +import java.util.Stack; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; public class MemTest { + HashMap m = new HashMap(); + HashMap m1 = new HashMap(1); + ConcurrentHashMap cm = new ConcurrentHashMap(); + ConcurrentHashMap cm1 = new ConcurrentHashMap(1, 0.75f, 1); + ConcurrentSkipListMap csm = new ConcurrentSkipListMap(); + Hashtable ht = new Hashtable(); + Properties p = new Properties(); + TreeMap t = new TreeMap(); + LinkedHashMap l = new LinkedHashMap(); + + TreeSet ts = new TreeSet(); + HashSet hs = new HashSet(); + LinkedHashSet lhs = new LinkedHashSet(); + + ArrayList list = new ArrayList(); + ArrayList list1 = new ArrayList(1); + + CopyOnWriteArrayList cpl = new CopyOnWriteArrayList(); + CopyOnWriteArraySet cps = new CopyOnWriteArraySet(); + Vector v = new Vector(); + LinkedList ll = new LinkedList(); + Stack stack = new Stack(); + PriorityQueue pq = new PriorityQueue(); + ConcurrentLinkedQueue clq = new ConcurrentLinkedQueue(); + public static void main(String[] args) throws Exception { -// DruidDataSource dataSource = new DruidDataSource(); -// dataSource.setUrl("jdbc:mock:xxx"); -// dataSource.setInitialSize(1); -// dataSource.setDbType("mysql"); -// dataSource.setFilters("mergeStat"); - // dataSource.setPoolPreparedStatements(true); - // dataSource.setMaxOpenPreparedStatements(50); - - // for (int i = 1000; i < 2000; ++i) { - // String tableName = "t" + i; - // String sql = "select * from " + tableName + " where " + tableName + ".id = " + i; - // Connection conn = dataSource.getConnection(); - // - // PreparedStatement stmt = conn.prepareStatement(sql); - // stmt.execute(); - // stmt.close(); - // - // conn.close(); - // } - - // Connection conn = dataSource.getConnection(); - // - String sql = "SELECT UMID, HWID, MAC, GUID, RID , GMT_CREATE, GMT_MODIFIED FROM umid_rid " + // - "WHERE RID = ? " + // - "LIMIT 10"; - // PreparedStatement stmt = conn.prepareStatement(sql); - // stmt.execute(); - - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, "mysql"); - List statementList = parser.parseStatementList(); - - SQLStatement stmt = statementList.get(0); - - StringBuilder out = new StringBuilder(); - SQLASTOutputVisitor visitor = ParameterizedOutputVisitorUtils.createParameterizedOutputVisitor(out, "mysql"); - stmt.accept(visitor); + MemTest o = new MemTest(); Thread.sleep(1000 * 1000); -// dataSource.close(); + + System.out.println(o); } } From 646ef3153b5e29482a2139f5949b40a1116d9334 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 29 Jun 2013 00:30:35 +0800 Subject: [PATCH 5/8] support mysql group_concat --- .../dialect/mysql/parser/MySqlExprParser.java | 20 +++++ .../mysql/visitor/MySqlOutputVisitor.java | 22 +++++- .../oracle/parser/OracleExprParser.java | 29 +------- .../postgresql/parser/PGExprParser.java | 23 ++---- .../sqlserver/parser/SQLServerExprParser.java | 56 ++++++-------- .../druid/sql/parser/SQLExprParser.java | 18 +++-- .../sql/visitor/SQLASTOutputVisitor.java | 7 ++ .../bvt/sql/mysql/MySqlSelectTest_12.java | 70 ++++++++++++++++++ .../mysql/MySqlSelectTest_group_concat.java | 74 +++++++++++++++++++ .../mysql/MySqlSelectTest_group_concat_2.java | 72 ++++++++++++++++++ 10 files changed, 306 insertions(+), 85 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_12.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat_2.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 a3a5777e93..56b8baf69f 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 @@ -18,6 +18,8 @@ package com.alibaba.druid.sql.dialect.mysql.parser; import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLOrderBy; +import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; @@ -55,8 +57,11 @@ import com.alibaba.druid.sql.parser.Token; public class MySqlExprParser extends SQLExprParser { + public static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "GROUP_CONCAT", "MAX", "MIN", "STDDEV", "SUM" }; + public MySqlExprParser(Lexer lexer){ super(lexer); + this.aggregateFunctions = AGGREGATE_FUNCTIONS; } public MySqlExprParser(String sql){ @@ -769,4 +774,19 @@ public class MySqlExprParser extends SQLExprParser { accept(Token.RPAREN); return fk; } + + protected SQLAggregateExpr parseAggregateExprRest(SQLAggregateExpr aggregateExpr) { + if (lexer.token() == Token.ORDER) { + SQLOrderBy orderBy = this.parseOrderBy(); + aggregateExpr.putAttribute("ORDER BY", orderBy); + } + if (identifierEquals("SEPARATOR")) { + lexer.nextToken(); + + SQLExpr seperator = this.primary(); + + aggregateExpr.putAttribute("SEPARATOR", seperator); + } + return aggregateExpr; + } } 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 e1efa7860e..3bb2c34bad 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 @@ -22,7 +22,9 @@ import com.alibaba.druid.sql.ast.SQLCommentHint; 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.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLSetQuantifier; +import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLNullExpr; @@ -594,8 +596,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV && (!varName.equals("?")) // && (!varName.startsWith("#")) // && (!varName.startsWith("$")) // - && (!varName.startsWith(":")) - ) { + && (!varName.startsWith(":"))) { print("@@"); } } @@ -3061,4 +3062,21 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } + protected void visitAggreateRest(SQLAggregateExpr aggregateExpr) { + { + SQLOrderBy value = (SQLOrderBy) aggregateExpr.getAttribute("ORDER BY"); + if (value != null) { + print(" "); + ((SQLObject) value).accept(this); + } + } + { + Object value = aggregateExpr.getAttribute("SEPARATOR"); + if (value != null) { + print(" SEPARATOR "); + ((SQLObject) value).accept(this); + } + } + } + } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index dbd4d15df7..c84003327f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -72,22 +72,6 @@ import com.alibaba.druid.sql.parser.Token; public class OracleExprParser extends SQLExprParser { - - - - - - - - - - - - - - - - public boolean allowStringAdditive = false; /** @@ -137,10 +121,11 @@ public class OracleExprParser extends SQLExprParser { public OracleExprParser(Lexer lexer){ super(lexer); + this.aggregateFunctions = AGGREGATE_FUNCTIONS; } public OracleExprParser(String text){ - super(new OracleLexer(text)); + this(new OracleLexer(text)); this.lexer.nextToken(); } @@ -267,16 +252,6 @@ public class OracleExprParser extends SQLExprParser { return parseDataTypeRest(dataType); } - public boolean isAggreateFunction(String word) { - for (int i = 0; i < AGGREGATE_FUNCTIONS.length; ++i) { - if (AGGREGATE_FUNCTIONS[i].compareToIgnoreCase(word) == 0) { - return true; - } - } - - return false; - } - public SQLExpr primary() { final Token tok = lexer.token(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java index 0cb3c1266c..394364c024 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java @@ -25,25 +25,16 @@ import com.alibaba.druid.sql.parser.Token; public class PGExprParser extends SQLExprParser { + public final static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM", "ROW_NUMBER" }; + public PGExprParser(String sql){ - super(new PGLexer(sql)); + this(new PGLexer(sql)); this.lexer.nextToken(); } public PGExprParser(Lexer lexer){ super(lexer); - } - - public boolean isAggreateFunction(String word) { - String[] aggregateFunctions = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM", "ROW_NUMBER" }; - - for (int i = 0; i < aggregateFunctions.length; ++i) { - if (aggregateFunctions[i].compareToIgnoreCase(word) == 0) { - return true; - } - } - - return false; + this.aggregateFunctions = AGGREGATE_FUNCTIONS; } @Override @@ -71,16 +62,16 @@ public class PGExprParser extends SQLExprParser { return null; } - + public SQLExpr primaryRest(SQLExpr expr) { if (lexer.token() == Token.COLONCOLON) { lexer.nextToken(); SQLExpr typeExpr = this.expr(); SQLBinaryOpExpr castExpr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PostgresStyleTypeCast, typeExpr); - + return primaryRest(castExpr); } - + return super.primaryRest(expr); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java index e9d8cc3838..f98b5b0a15 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -26,28 +26,30 @@ import com.alibaba.druid.sql.parser.Token; public class SQLServerExprParser extends SQLExprParser { + public final static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "MAX", "MIN", "ROW_NUMBER", "STDDEV", "SUM" }; + public SQLServerExprParser(Lexer lexer){ super(lexer); + this.aggregateFunctions = AGGREGATE_FUNCTIONS; } - public SQLServerExprParser(String sql) { - super(new SQLServerLexer(sql)); + public SQLServerExprParser(String sql){ + this(new SQLServerLexer(sql)); this.lexer.nextToken(); } - + public SQLExpr primary() { - - + if (lexer.token() == Token.LBRACKET) { lexer.nextToken(); SQLExpr name = this.name(); accept(Token.RBRACKET); return primaryRest(name); } - + return super.primary(); } - + public SQLServerSelectParser createSelectParser() { return new SQLServerSelectParser(this); } @@ -56,31 +58,31 @@ public class SQLServerExprParser extends SQLExprParser { if (lexer.token() == Token.DOTDOT) { expr = nameRest((SQLName) expr); } - + return super.primaryRest(expr); } - + protected SQLExpr dotRest(SQLExpr expr) { boolean backet = false; - + if (lexer.token() == Token.LBRACKET) { lexer.nextToken(); backet = true; } - + expr = super.dotRest(expr); if (backet) { accept(Token.RBRACKET); } - + return expr; } - + public SQLName nameRest(SQLName expr) { if (lexer.token() == Token.DOTDOT) { lexer.nextToken(); - + boolean backet = false; if (lexer.token() == Token.LBRACKET) { lexer.nextToken(); @@ -88,7 +90,7 @@ public class SQLServerExprParser extends SQLExprParser { } String text = lexer.stringVal(); lexer.nextToken(); - + if (backet) { accept(Token.RBRACKET); } @@ -99,44 +101,32 @@ public class SQLServerExprParser extends SQLExprParser { return super.nameRest(expr); } - - public boolean isAggreateFunction(String word) { - String[] aggregateFunctions = { "AVG", "COUNT", "MAX", "MIN", "ROW_NUMBER", "STDDEV", "SUM" }; - for (int i = 0; i < aggregateFunctions.length; ++i) { - if (aggregateFunctions[i].compareToIgnoreCase(word) == 0) { - return true; - } - } - - return false; - } - public SQLServerTop parseTop() { if (lexer.token() == Token.TOP) { SQLServerTop top = new SQLServerTop(); lexer.nextToken(); - + boolean paren = false; if (lexer.token() == Token.LPAREN) { paren = true; lexer.nextToken(); } - + top.setExpr(primary()); - + if (paren) { accept(Token.RPAREN); } - + if (lexer.token() == Token.PERCENT) { lexer.nextToken(); top.setPercent(true); } - + return top; } - + return null; } } 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 484e3101f4..925786c581 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -71,6 +71,10 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; public class SQLExprParser extends SQLParser { + public final static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM" }; + + protected String[] aggregateFunctions = AGGREGATE_FUNCTIONS; + public SQLExprParser(String sql){ super(sql); } @@ -703,8 +707,6 @@ public class SQLExprParser extends SQLParser { } public boolean isAggreateFunction(String word) { - String[] aggregateFunctions = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM" }; - for (int i = 0; i < aggregateFunctions.length; ++i) { if (aggregateFunctions[i].compareToIgnoreCase(word) == 0) { return true; @@ -728,7 +730,9 @@ public class SQLExprParser extends SQLParser { aggregateExpr = new SQLAggregateExpr(methodName); } - exprList(aggregateExpr.getArguments()); + exprList(aggregateExpr.getArguments(), aggregateExpr); + + parseAggregateExprRest(aggregateExpr); accept(Token.RPAREN); @@ -752,10 +756,6 @@ public class SQLExprParser extends SQLParser { over.setOrderBy(parseOrderBy()); - // if (over.getOrderBy() != null) { - // //TODO window - // } - accept(Token.RPAREN); aggregateExpr.setOver(over); @@ -764,6 +764,10 @@ public class SQLExprParser extends SQLParser { return aggregateExpr; } + protected SQLAggregateExpr parseAggregateExprRest(SQLAggregateExpr aggregateExpr) { + return aggregateExpr; + } + public SQLOrderBy parseOrderBy() { if (lexer.token() == Token.ORDER) { SQLOrderBy orderBy = new SQLOrderBy(); 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 0608dce45a..240be1f789 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -511,6 +511,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } printAndAccept(x.getArguments(), ", "); + + visitAggreateRest(x); + print(")"); if (x.getOver() != null) { @@ -519,6 +522,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } return false; } + + protected void visitAggreateRest(SQLAggregateExpr aggregateExpr) { + + } public boolean visit(SQLAllColumnExpr x) { print("*"); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_12.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_12.java new file mode 100644 index 0000000000..b86e02316e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_12.java @@ -0,0 +1,70 @@ +/* + * 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 java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class MySqlSelectTest_12 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT COUNT(*) a FROM (select nickname,mobile,comment,createdate from ub_userdiscuss order by discuss_id desc) b "; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; + + SQLSelect select = selectStmt.getSelect(); + Assert.assertNotNull(select.getQuery()); + MySqlSelectQueryBlock queryBlock = (MySqlSelectQueryBlock) select.getQuery(); + Assert.assertNull(queryBlock.getOrderBy()); + + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(5, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + Assert.assertEquals(1, visitor.getOrderByColumns().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("ub_userdiscuss"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("SELECT COUNT(*) AS a" + // + "\nFROM (SELECT nickname, mobile, comment, createdate" + // + "\n\tFROM ub_userdiscuss" + // + "\n\tORDER BY discuss_id DESC" + // + "\n\t) b", // + output); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat.java new file mode 100644 index 0000000000..fc63490b08 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat.java @@ -0,0 +1,74 @@ +/* + * 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 java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class MySqlSelectTest_group_concat extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT GROUP_CONCAT(ext_customer_id Separator '.') " // + + "from ad_texts " // + + "where customer_id=13001 " // + + "and description1 like '%爱丽%' " // + + "order by id asc;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; + + SQLSelect select = selectStmt.getSelect(); + Assert.assertNotNull(select.getQuery()); + MySqlSelectQueryBlock queryBlock = (MySqlSelectQueryBlock) select.getQuery(); + Assert.assertNotNull(queryBlock.getOrderBy()); + + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(4, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + Assert.assertEquals(1, visitor.getOrderByColumns().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("ad_texts"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("SELECT GROUP_CONCAT(ext_customer_id SEPARATOR '.')" // + + "\nFROM ad_texts" // + + "\nWHERE customer_id = 13001" // + + "\n\tAND description1 LIKE '%爱丽%'" // + + "\nORDER BY id ASC", // + output); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat_2.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat_2.java new file mode 100644 index 0000000000..bcde1d7c82 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_group_concat_2.java @@ -0,0 +1,72 @@ +/* + * 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 java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class MySqlSelectTest_group_concat_2 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT student_name, " // + + "GROUP_CONCAT(DISTINCT test_score " // + + " ORDER BY test_score DESC SEPARATOR ' ') " // + + "FROM student " // + + "GROUP BY student_name"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; + + SQLSelect select = selectStmt.getSelect(); + Assert.assertNotNull(select.getQuery()); + MySqlSelectQueryBlock queryBlock = (MySqlSelectQueryBlock) select.getQuery(); + Assert.assertNull(queryBlock.getOrderBy()); + + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(2, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + Assert.assertEquals(0, visitor.getOrderByColumns().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("student"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("SELECT student_name, GROUP_CONCAT(DISTINCT test_score ORDER BY test_score DESC SEPARATOR ' ')" // + + "\nFROM student" // + + "\nGROUP BY student_name", // + output); + } +} From ed17503ff85c267132a160c74e87df0e03cee350 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 30 Jun 2013 16:56:24 +0800 Subject: [PATCH 6/8] fixed MySqlExceptionSorter --- .../pool/vendor/MySqlExceptionSorter.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java b/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java index d09dcae74b..b35240d67b 100644 --- a/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java +++ b/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java @@ -71,15 +71,21 @@ public class MySqlExceptionSorter implements ExceptionSorter { case 1037: // ER_OUTOFMEMORY case 1038: // ER_OUT_OF_SORTMEMORY return true; + default: + break; + } + + if (errorCode >= -10000 && errorCode <= -9000) { + return true; } - if (StringUtils.isNotBlank(e.getMessage())) { - final String errorText = e.getMessage().toUpperCase(); + String message = e.getMessage(); + if (message != null && message.length() > 0) { + final String errorText = message.toUpperCase(); - if (errorCode == 0 - && (errorText.indexOf("COMMUNICATIONS LINK FAILURE") > -1 || errorText - .indexOf("COULD NOT CREATE CONNECTION") > -1) - || errorText.indexOf("NO DATASOURCE") > -1 + if ((errorCode == 0 && (errorText.indexOf("COMMUNICATIONS LINK FAILURE") > -1) // + || errorText.indexOf("COULD NOT CREATE CONNECTION") > -1) // + || errorText.indexOf("NO DATASOURCE") > -1 // || errorText.indexOf("NO ALIVE DATASOURCE") > -1) { return true; } @@ -87,4 +93,10 @@ public class MySqlExceptionSorter implements ExceptionSorter { return false; } + @Override + public void configFromProperties(Properties properties) { + // TODO Auto-generated method stub + + } + } From 7436dd49102734f03ce4966d046c9fc631131224 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 30 Jun 2013 16:57:16 +0800 Subject: [PATCH 7/8] 0.2.22 --- src/main/java/com/alibaba/druid/VERSION.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/VERSION.java b/src/main/java/com/alibaba/druid/VERSION.java index e4ce36146b..1ceac470fc 100644 --- a/src/main/java/com/alibaba/druid/VERSION.java +++ b/src/main/java/com/alibaba/druid/VERSION.java @@ -19,7 +19,7 @@ public final class VERSION { public final static int MajorVersion = 0; public final static int MinorVersion = 2; - public final static int RevisionVersion = 21; + public final static int RevisionVersion = 22; public static String getVersionNumber() { return VERSION.MajorVersion + "." + VERSION.MinorVersion + "." + VERSION.RevisionVersion; From 97f763ce4b6f15503308196efe3575c008900f17 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 30 Jun 2013 17:36:06 +0800 Subject: [PATCH 8/8] fixed MySqlExceptionSorter --- .../pool/vendor/MySqlExceptionSorter.java | 23 +------------------ .../MySqlExceptionSorterTest_oceanbase.java | 3 ++- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java b/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java index b35240d67b..dbec6b9776 100644 --- a/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java +++ b/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java @@ -24,28 +24,8 @@ public class MySqlExceptionSorter implements ExceptionSorter { @Override public boolean isExceptionFatal(SQLException e) { - int loopCount = 20; - - Throwable cause = e; - while (cause != null) { - if (cause instanceof SQLException) { - SQLException sqlException = (SQLException) cause; - - if (isExceptionFatal0(sqlException)) { - return true; - } - } - cause = cause.getCause(); - if (--loopCount < 0) { - break; - } - } - return false; - } - - private boolean isExceptionFatal0(SQLException e) { String sqlState = e.getSQLState(); - final int errorCode = Math.abs(e.getErrorCode()); + final int errorCode = e.getErrorCode(); if (sqlState != null && sqlState.startsWith("08")) { return true; @@ -95,7 +75,6 @@ public class MySqlExceptionSorter implements ExceptionSorter { @Override public void configFromProperties(Properties properties) { - // TODO Auto-generated method stub } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_oceanbase.java b/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_oceanbase.java index 04bd235ed3..d162c663a6 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_oceanbase.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_oceanbase.java @@ -12,7 +12,8 @@ import com.alibaba.druid.pool.vendor.MySqlExceptionSorter; public class MySqlExceptionSorterTest_oceanbase extends TestCase { public void test_true() throws Exception { MySqlExceptionSorter sorter = new MySqlExceptionSorter(); - Assert.assertTrue(sorter.isExceptionFatal(new SQLException("", "", -9000))); + SQLException exception = new SQLException("", "", -9000); + Assert.assertTrue(sorter.isExceptionFatal(exception)); } public void test_true_1() throws Exception {