From efbeb8336edf11f5d89d98ba484c86c456441c11 Mon Sep 17 00:00:00 2001 From: wenshao Date: Fri, 26 Jul 2013 17:56:38 +0800 Subject: [PATCH 1/9] change LogImpl's order --- src/main/java/com/alibaba/druid/support/logging/LogFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/support/logging/LogFactory.java b/src/main/java/com/alibaba/druid/support/logging/LogFactory.java index 04be43ea72..2ccaf7e95f 100644 --- a/src/main/java/com/alibaba/druid/support/logging/LogFactory.java +++ b/src/main/java/com/alibaba/druid/support/logging/LogFactory.java @@ -27,10 +27,10 @@ public class LogFactory { // 优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息 tryImplementation("org.apache.log4j.Logger", "com.alibaba.druid.support.logging.Log4jImpl"); - tryImplementation("java.util.logging.Logger", "com.alibaba.druid.support.logging.Jdk14LoggingImpl"); tryImplementation("org.slf4j.Logger", "com.alibaba.druid.support.logging.SLF4JImpl"); tryImplementation("org.apache.commons.logging.LogFactory", "com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl"); + tryImplementation("java.util.logging.Logger", "com.alibaba.druid.support.logging.Jdk14LoggingImpl"); if (logConstructor == null) { try { From df2062957c7054b3ccec00a528c3953cdad84c7f Mon Sep 17 00:00:00 2001 From: wenshao Date: Fri, 26 Jul 2013 18:22:00 +0800 Subject: [PATCH 2/9] improve weburi stat --- .../druid/proxy/jdbc/StatementProxyImpl.java | 14 ++-- .../druid/support/http/stat/WebURIStat.java | 75 ++++++++++++++++++- .../support/http/stat/WebURIStatValue.java | 22 ++++++ 3 files changed, 104 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java index db76323977..c8aa5d33b8 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java @@ -48,7 +48,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro protected StatementExecuteType lastExecuteType; - protected Integer updateCount = null; + protected Integer updateCount = null; private FilterChainImpl filterChain = null; @@ -319,9 +319,11 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public boolean getMoreResults() throws SQLException { - updateCount = null; FilterChainImpl chain = createChain(); boolean value = chain.statement_getMoreResults(this); + if (value) { + updateCount = null; + } recycleFilterChain(chain); return value; } @@ -549,21 +551,21 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro public boolean isFirstResultSet() { return firstResultSet; } - + @SuppressWarnings("unchecked") public T unwrap(Class iface) throws SQLException { if (iface == StatementProxy.class) { return (T) this; } - + return super.unwrap(iface); } - + public boolean isWrapperFor(Class iface) throws SQLException { if (iface == StatementProxy.class) { return true; } - + return super.isWrapperFor(iface); } diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java index c32a5fd87c..54d18882d6 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java @@ -102,6 +102,32 @@ public class WebURIStat { private final static ThreadLocal currentLocal = new ThreadLocal(); + private volatile long histogram_0_1; + private volatile long histogram_1_10; + private volatile long histogram_10_100; + private volatile long histogram_100_1000; + private volatile int histogram_1000_10000; + private volatile int histogram_10000_100000; + private volatile int histogram_100000_1000000; + private volatile int histogram_1000000_more; + + final static AtomicLongFieldUpdater histogram_0_1_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_0_1"); + final static AtomicLongFieldUpdater histogram_1_10_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_1_10"); + final static AtomicLongFieldUpdater histogram_10_100_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_10_100"); + final static AtomicLongFieldUpdater histogram_100_1000_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_100_1000"); + final static AtomicIntegerFieldUpdater histogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_1000_10000"); + final static AtomicIntegerFieldUpdater histogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_10000_100000"); + final static AtomicIntegerFieldUpdater histogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_100000_1000000"); + final static AtomicIntegerFieldUpdater histogram_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_1000000_more"); + public WebURIStat(String uri){ super(); this.uri = uri; @@ -145,6 +171,8 @@ public class WebURIStat { runningCountUpdater.decrementAndGet(this); requestTimeNanoUpdater.addAndGet(this, nanos); + histogramRecord(nanos); + if (error != null) { errorCountUpdater.incrementAndGet(this); } @@ -212,6 +240,28 @@ public class WebURIStat { currentLocal.set(null); } + private void histogramRecord(long nanos) { + final long millis = nanos / 1000 / 1000; + + if (millis < 1) { + histogram_0_1_Updater.incrementAndGet(this); + } else if (millis < 10) { + histogram_1_10_Updater.incrementAndGet(this); + } else if (millis < 100) { + histogram_10_100_Updater.incrementAndGet(this); + } else if (millis < 1000) { + histogram_100_1000_Updater.incrementAndGet(this); + } else if (millis < 10000) { + histogram_1000_10000_Updater.incrementAndGet(this); + } else if (millis < 100000) { + histogram_10000_100000_Updater.incrementAndGet(this); + } else if (millis < 1000000) { + histogram_100000_1000000_Updater.incrementAndGet(this); + } else { + histogram_1000000_more_Updater.incrementAndGet(this); + } + } + public int getRunningCount() { return this.runningCount; } @@ -364,6 +414,20 @@ public class WebURIStat { return profiletat; } + public long[] getHistogramValues() { + return new long[] { + // + histogram_0_1, // + histogram_1_10, // + histogram_10_100, // + histogram_100_1000, // + histogram_1000_10000, // + histogram_10000_100000, // + histogram_100000_1000000, // + histogram_1000000_more // + }; + } + public WebURIStatValue getValue(boolean reset) { WebURIStatValue val = new WebURIStatValue(); @@ -399,11 +463,20 @@ public class WebURIStat { val.setLastAccessTimeMillis(get(this, lastAccessTimeMillisUpdater, reset)); val.setProfileEntryStatValueList(this.getProfiletat().getStatValue(reset)); + + val.histogram_0_1 = get(this, histogram_0_1_Updater, reset); + val.histogram_1_10 = get(this, histogram_1_10_Updater, reset); + val.histogram_10_100 = get(this, histogram_10_100_Updater, reset); + val.histogram_100_1000 = get(this, histogram_100_1000_Updater, reset); + val.histogram_1000_10000 = get(this, histogram_1000_10000_Updater, reset); + val.histogram_10000_100000 = get(this, histogram_10000_100000_Updater, reset); + val.histogram_100000_1000000 = get(this, histogram_100000_1000000_Updater, reset); + val.histogram_1000000_more = get(this, histogram_1000000_more_Updater, reset); return val; } public Map getStatData() { - return getValue(false).getStatData(); + return getValue(false).getStatData(); } } diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java index 13434cc1af..712f9abf63 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java @@ -58,6 +58,27 @@ public class WebURIStatValue { private List profileEntryStatValueList; + protected long histogram_0_1; + protected long histogram_1_10; + protected long histogram_10_100; + protected long histogram_100_1000; + protected int histogram_1000_10000; + protected int histogram_10000_100000; + protected int histogram_100000_1000000; + protected int histogram_1000000_more; + + public long[] getHistogram() { + return new long[] { histogram_0_1, // + histogram_1_10, // + histogram_10_100, // + histogram_100_1000, // + histogram_1000_10000, // + histogram_10000_100000, // + histogram_100000_1000000, // + histogram_1000000_more, // + }; + } + public List getProfileEntryStatValueList() { return profileEntryStatValueList; } @@ -280,6 +301,7 @@ public class WebURIStatValue { data.put("JdbcResultSetOpenCount", this.getJdbcResultSetOpenCount()); data.put("JdbcResultSetCloseCount", this.getJdbcResultSetCloseCount()); + data.put("Histogram", this.getHistogram()); if (this.profileEntryStatValueList != null) { int size = profileEntryStatValueList.size(); From 52015e7681d2d6e494a292e49146b0ca0cf8ae9b Mon Sep 17 00:00:00 2001 From: wenshao Date: Fri, 26 Jul 2013 19:04:50 +0800 Subject: [PATCH 3/9] fixed testcase --- .../com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java index d59158a1fa..ca10383607 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java @@ -21,7 +21,7 @@ public class PagerUtilsTest_Limit_db2_0 extends TestCase { String sql = "select * from t"; String result = PagerUtils.limit(sql, JdbcConstants.DB2, 10, 10); Assert.assertEquals("SELECT *"// - + "\nFROM (SELECT *, ROW_NUMBER() AS ROWNUM"// + + "\nFROM (SELECT *, ROW_NUMBER() OVER () AS ROWNUM"// + "\n\tFROM t"// + "\n\t) XX"// + "\nWHERE ROWNUM > 10"// @@ -32,7 +32,7 @@ public class PagerUtilsTest_Limit_db2_0 extends TestCase { String sql = "select * from t where age > 100"; String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10); Assert.assertEquals("SELECT *"// - + "\nFROM (SELECT *, ROW_NUMBER() AS ROWNUM"// + + "\nFROM (SELECT *, ROW_NUMBER() OVER () AS ROWNUM"// + "\n\tFROM t"// + "\n\tWHERE age > 100"// + "\n\t) XX"// From d5991f3b9b10e3339cacff53233a8ff9f19b5ede Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 27 Jul 2013 15:27:51 +0800 Subject: [PATCH 4/9] add testcase & bug fixed --- .../sql/dialect/oracle/ast/stmt/OracleStatementImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleStatementImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleStatementImpl.java index 941449295b..ca37636d58 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleStatementImpl.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleStatementImpl.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -28,4 +29,8 @@ public abstract class OracleStatementImpl extends SQLStatementImpl implements Or } public abstract void accept0(OracleASTVisitor visitor); + + public String toString() { + return SQLUtils.toOracleString(this); + } } From 4f0f2ae90b920b7e64fb9de7bf1bcec1cdc6fb29 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 27 Jul 2013 15:34:13 +0800 Subject: [PATCH 5/9] bug fixed for toString --- .../druid/sql/ast/SQLStatementImpl.java | 73 ++++++++++--------- .../bvt/sql/oracle/OracleMergeTest7.java | 61 ++++++++++++++++ 2 files changed, 98 insertions(+), 36 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java index 7f7ae9a420..e800cb3d3a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java @@ -1,36 +1,37 @@ -/* - * 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.sql.ast; - -import com.alibaba.druid.sql.visitor.SQLASTVisitor; - -public abstract class SQLStatementImpl extends SQLObjectImpl implements SQLStatement { - - private static final long serialVersionUID = 1L; - - public SQLStatementImpl(){ - - } - - public void output(StringBuffer buf) { - buf.append(super.toString()); - } - - @Override - protected void accept0(SQLASTVisitor visitor) { - throw new UnsupportedOperationException(this.getClass().getName()); - } -} +/* + * 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.sql.ast; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public abstract class SQLStatementImpl extends SQLObjectImpl implements SQLStatement { + + private static final long serialVersionUID = 1L; + + public SQLStatementImpl(){ + + } + + public String toString() { + return SQLUtils.toSQLString(this); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + throw new UnsupportedOperationException(this.getClass().getName()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java new file mode 100644 index 0000000000..8085e5b8c7 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java @@ -0,0 +1,61 @@ +/* + * 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.oracle; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.parser.SQLStatementParser; + +public class OracleMergeTest7 extends OracleTest { + + public void test_0() throws Exception { + String sql = "MERGE INTO copy_emp c " + // + "USING employees e " + // + "ON (c.employee_id=e.employee_id) " + // + "WHEN MATCHED THEN " + // + "UPDATE SET " + // + "c.first_name=e.first_name, " + // + "c.last_name=e.last_name, " + // + "c.department_id=e.department_id " + // + "WHEN NOT MATCHED THEN " + // + "INSERT VALUES(e.employee_id,e.first_name,e.last_name," + // + "e.email,e.phone_number,e.hire_date,e.job_id, " + // + "e.salary,e.commission_pct,e.manager_id,e.department_id)"; + + SQLStatementParser parser = new OracleStatementParser(sql); + List stmtList = parser.parseStatementList(); + OracleMergeStatement mergeStatement = (OracleMergeStatement) stmtList.get(0); + String result = SQLUtils.toOracleString(mergeStatement); + Assert.assertEquals("MERGE INTO copy_emp c" // + + "\nUSING employees e ON c.employee_id = e.employee_id" // + + "\nWHEN MATCHED THEN UPDATE SET c.first_name = e.first_name, c.last_name = e.last_name, c.department_id = e.department_id" // + + "\nWHEN NOT MATCHED THEN INSERT VALUES (e.employee_id, e.first_name, e.last_name, e.email, e.phone_number, e.hire_date, e.job_id, e.salary, e.commission_pct, e.manager_id, e.department_id)", + result); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "employee_id"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "department_id"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("bonuses", "employee_id"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("bonuses", "bonus"))); + } + +} From 58174442a438a86d6ca80e380bad7e5de3b550ce Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 27 Jul 2013 15:48:06 +0800 Subject: [PATCH 6/9] improve PageUtils --- .../com/alibaba/druid/sql/PagerUtils.java | 80 ++++++++++++++----- .../sql/PagerUtilsTest_Limit_SQLServer_1.java | 27 +++++++ .../bvt/sql/PagerUtilsTest_Limit_db2_1.java | 27 +++++++ 3 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index 89e429c4b8..8aefdb15cf 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -92,7 +92,7 @@ public class PagerUtils { if (JdbcConstants.DB2.equals(dbType)) { return limitDB2(select, dbType, offset, count); } - + if (JdbcConstants.SQL_SERVER.equals(dbType)) { return limitSQLServer(select, dbType, offset, count); } @@ -118,6 +118,14 @@ public class PagerUtils { private static String limitDB2(SQLSelect select, String dbType, int offset, int count) { SQLSelectQuery query = select.getQuery(); + SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // + SQLBinaryOperator.GreaterThan, // + new SQLNumberExpr(offset)); + SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // + SQLBinaryOperator.LessThanOrEqual, // + new SQLNumberExpr(count + offset)); + SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); + if (query instanceof SQLSelectQueryBlock) { DB2SelectQueryBlock queryBlock = (DB2SelectQueryBlock) query; if (offset <= 0) { @@ -137,25 +145,44 @@ public class PagerUtils { countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); - SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // - SQLBinaryOperator.GreaterThan, // - new SQLNumberExpr(offset)); - SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // - SQLBinaryOperator.LessThanOrEqual, // - new SQLNumberExpr(count + offset)); - SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); - countQueryBlock.setWhere(pageCondition); return SQLUtils.toSQLString(countQueryBlock, dbType); } - return SQLUtils.toSQLString(select, dbType); + DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); + countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*"))); + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); + SQLOrderBy orderBy = select.getOrderBy(); + aggregateExpr.setOver(new SQLOver(orderBy)); + select.setOrderBy(null); + countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); + + countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); + + if (offset <= 0) { + return SQLUtils.toSQLString(countQueryBlock, dbType); + } + + DB2SelectQueryBlock offsetQueryBlock = new DB2SelectQueryBlock(); + offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); + offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); + offsetQueryBlock.setWhere(pageCondition); + + return SQLUtils.toSQLString(offsetQueryBlock, dbType); } - + private static String limitSQLServer(SQLSelect select, String dbType, int offset, int count) { SQLSelectQuery query = select.getQuery(); + SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // + SQLBinaryOperator.GreaterThan, // + new SQLNumberExpr(offset)); + SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // + SQLBinaryOperator.LessThanOrEqual, // + new SQLNumberExpr(count + offset)); + SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); + if (query instanceof SQLSelectQueryBlock) { SQLServerSelectQueryBlock queryBlock = (SQLServerSelectQueryBlock) query; if (offset <= 0) { @@ -172,25 +199,36 @@ public class PagerUtils { queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); - DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); + SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock(); countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); - SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // - SQLBinaryOperator.GreaterThan, // - new SQLNumberExpr(offset)); - SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // - SQLBinaryOperator.LessThanOrEqual, // - new SQLNumberExpr(count + offset)); - SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); - countQueryBlock.setWhere(pageCondition); return SQLUtils.toSQLString(countQueryBlock, dbType); } - return SQLUtils.toSQLString(select, dbType); + SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock(); + countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*"))); + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); + SQLOrderBy orderBy = select.getOrderBy(); + aggregateExpr.setOver(new SQLOver(orderBy)); + select.setOrderBy(null); + countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); + + countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); + + if (offset <= 0) { + return SQLUtils.toSQLString(countQueryBlock, dbType); + } + + SQLServerSelectQueryBlock offsetQueryBlock = new SQLServerSelectQueryBlock(); + offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); + offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); + offsetQueryBlock.setWhere(pageCondition); + + return SQLUtils.toSQLString(offsetQueryBlock, dbType); } private static String limitOracle(SQLSelect select, String dbType, int offset, int count) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java new file mode 100644 index 0000000000..f0c0f59c7b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_SQLServer_1 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 union select * from t2"; + String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 20, 10); + Assert.assertEquals("SELECT *" // + + "\nFROM (SELECT XX.*, ROW_NUMBER() OVER () AS ROWNUM" // + + "\n\tFROM (SELECT *" // + + "\n\t\tFROM t1" // + + "\n\t\tUNION" // + + "\n\t\tSELECT *" // + + "\n\t\tFROM t2" // + + "\n\t\t) XX" // + + "\n\t) XXX" // + + "\nWHERE ROWNUM > 20" // + + "\n\tAND ROWNUM <= 30", result); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java new file mode 100644 index 0000000000..48c785bb6e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_db2_1 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 union select * from t2"; + String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10); + Assert.assertEquals("SELECT *" // + + "\nFROM (SELECT XX.*, ROW_NUMBER() OVER () AS ROWNUM" // + + "\n\tFROM (SELECT *" // + + "\n\t\tFROM t1" // + + "\n\t\tUNION" // + + "\n\t\tSELECT *" // + + "\n\t\tFROM t2" // + + "\n\t\t) XX" // + + "\n\t) XXX" // + + "\nWHERE ROWNUM > 20" // + + "\n\tAND ROWNUM <= 30", result); + } +} From c65c28e9b2aeb310d849f237daf4184025ac0aff Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 27 Jul 2013 20:54:03 +0800 Subject: [PATCH 7/9] PageUtils support SQL Server --- .../com/alibaba/druid/sql/PagerUtils.java | 21 +++++++++-------- .../sql/PagerUtilsTest_Limit_SQLServer_2.java | 23 +++++++++++++++++++ .../sql/PagerUtilsTest_Limit_SQLServer_3.java | 19 +++++++++++++++ .../sql/PagerUtilsTest_Limit_SQLServer_4.java | 23 +++++++++++++++++++ 4 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_3.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_4.java diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index 8aefdb15cf..7fab066394 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -192,10 +192,8 @@ public class PagerUtils { SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); SQLOrderBy orderBy = select.getOrderBy(); - if (orderBy != null) { - aggregateExpr.setOver(new SQLOver(orderBy)); - select.setOrderBy(null); - } + aggregateExpr.setOver(new SQLOver(orderBy)); + select.setOrderBy(null); queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); @@ -208,21 +206,24 @@ public class PagerUtils { return SQLUtils.toSQLString(countQueryBlock, dbType); } + SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock(); countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*"))); + + countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); + + if (offset <= 0) { + countQueryBlock.setTop(new SQLServerTop(new SQLNumberExpr(count))); + return SQLUtils.toSQLString(countQueryBlock, dbType); + } + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); SQLOrderBy orderBy = select.getOrderBy(); aggregateExpr.setOver(new SQLOver(orderBy)); select.setOrderBy(null); countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); - countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); - - if (offset <= 0) { - return SQLUtils.toSQLString(countQueryBlock, dbType); - } - SQLServerSelectQueryBlock offsetQueryBlock = new SQLServerSelectQueryBlock(); offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_2.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_2.java new file mode 100644 index 0000000000..22b90f5453 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_2.java @@ -0,0 +1,23 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_SQLServer_2 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 union select * from t2"; + String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 0, 10); + Assert.assertEquals("SELECT TOP 10 XX.*" // + + "\nFROM (SELECT *" // + + "\n\tFROM t1" // + + "\n\tUNION" // + + "\n\tSELECT *" // + + "\n\tFROM t2" // + + "\n\t) XX", result); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_3.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_3.java new file mode 100644 index 0000000000..babb5b1646 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_3.java @@ -0,0 +1,19 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_SQLServer_3 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 where id > 1"; + String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 0, 10); + Assert.assertEquals("SELECT TOP 10 *" // + + "\nFROM t1" // + + "\nWHERE id > 1", result); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_4.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_4.java new file mode 100644 index 0000000000..f3a38f5010 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_4.java @@ -0,0 +1,23 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_SQLServer_4 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 where id > 1"; + String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 100, 10); + Assert.assertEquals("SELECT *" // + + "\nFROM (SELECT *, ROW_NUMBER() OVER () AS ROWNUM" // + + "\n\tFROM t1" // + + "\n\tWHERE id > 1" // + + "\n\t) XX" // + + "\nWHERE ROWNUM > 100" // + + "\n\tAND ROWNUM <= 110", result); + } +} From 6e60d48b0a7ce11a06459aef1b8667d77589132d Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 28 Jul 2013 10:36:05 +0800 Subject: [PATCH 8/9] bug fixed for thread-safe init --- src/main/java/com/alibaba/druid/wall/WallFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/wall/WallFilter.java b/src/main/java/com/alibaba/druid/wall/WallFilter.java index 154ede83c8..8c947ed28e 100644 --- a/src/main/java/com/alibaba/druid/wall/WallFilter.java +++ b/src/main/java/com/alibaba/druid/wall/WallFilter.java @@ -59,7 +59,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean { public final static String ATTR_SQL_STAT = "wall.sqlStat"; @Override - public void init(DataSourceProxy dataSource) { + public synchronized void init(DataSourceProxy dataSource) { if (this.dbType == null || this.dbType.trim().length() == 0) { if (dataSource != null && dataSource.getDbType() != null) { this.dbType = dataSource.getDbType(); From 29dec6418efe8048171205864f6e3f8e6ec81235 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 28 Jul 2013 17:24:09 +0800 Subject: [PATCH 9/9] move license.txt location --- doc/license.txt => license.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename doc/license.txt => license.txt (91%) diff --git a/doc/license.txt b/license.txt similarity index 91% rename from doc/license.txt rename to license.txt index dbadc0ac15..696c2a748c 100644 --- a/doc/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright 1999-2011 Alibaba Group Holding Ltd. +Copyright 1999-2013 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.