bug fixed for duplicate getUpdateCount

This commit is contained in:
温少
2012-06-06 08:03:57 +08:00
parent 885d3c37ab
commit d70b5b21cd
10 changed files with 248 additions and 51 deletions
@@ -117,7 +117,7 @@ public class MockConnection extends ConnectionBase implements Connection {
throw new MockConnectionClosedException();
}
return new MockPreparedStatement(this, sql);
return createMockPreparedStatement(sql);
}
@Override
@@ -204,7 +204,7 @@ public class MockConnection extends ConnectionBase implements Connection {
throw new MockConnectionClosedException();
}
MockPreparedStatement stmt = new MockPreparedStatement(this, sql);
MockPreparedStatement stmt = createMockPreparedStatement(sql);
stmt.setResultSetType(resultSetType);
stmt.setResultSetConcurrency(resultSetConcurrency);
@@ -289,7 +289,7 @@ public class MockConnection extends ConnectionBase implements Connection {
throw new MockConnectionClosedException();
}
MockPreparedStatement stmt = new MockPreparedStatement(this, sql);
MockPreparedStatement stmt = createMockPreparedStatement(sql);
stmt.setResultSetType(resultSetType);
stmt.setResultSetConcurrency(resultSetConcurrency);
@@ -298,6 +298,16 @@ public class MockConnection extends ConnectionBase implements Connection {
return stmt;
}
private MockPreparedStatement createMockPreparedStatement(String sql) {
if (driver != null) {
MockPreparedStatementFactory preparedStatementFactory = driver.getPreparedStatementFactory();
if (preparedStatementFactory != null) {
return preparedStatementFactory.createMockPreparedStatement(this, sql);
}
}
return new MockPreparedStatement(this, sql);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
@@ -320,7 +330,7 @@ public class MockConnection extends ConnectionBase implements Connection {
throw new MockConnectionClosedException();
}
return new MockPreparedStatement(this, sql);
return createMockPreparedStatement(sql);
}
@Override
@@ -329,7 +339,7 @@ public class MockConnection extends ConnectionBase implements Connection {
throw new MockConnectionClosedException();
}
return new MockPreparedStatement(this, sql);
return createMockPreparedStatement(sql);
}
@Override
@@ -338,7 +348,7 @@ public class MockConnection extends ConnectionBase implements Connection {
throw new MockConnectionClosedException();
}
return new MockPreparedStatement(this, sql);
return createMockPreparedStatement(sql);
}
@Override
@@ -0,0 +1,8 @@
package com.alibaba.druid.mock;
import java.util.Properties;
public interface MockConnectionFactory {
MockConnection createConnection(MockDriver driver, String url, Properties connectProperties);
}
@@ -0,0 +1,12 @@
package com.alibaba.druid.mock;
import java.util.Properties;
public class MockConnectionFactoryImpl implements MockConnectionFactory {
@Override
public MockConnection createConnection(MockDriver driver, String url, Properties connectProperties) {
return new MockConnection(driver, url, connectProperties);
}
}
@@ -43,34 +43,53 @@ import com.alibaba.druid.support.logging.LogFactory;
public class MockDriver implements Driver, MockDriverMBean {
private final static Log LOG = LogFactory.getLog(MockDriver.class);
private final static Log LOG = LogFactory.getLog(MockDriver.class);
public final static MockExecuteHandler DEFAULT_HANDLER = new MySqlMockExecuteHandlerImpl();
public final static MockExecuteHandler DEFAULT_HANDLER = new MySqlMockExecuteHandlerImpl();
private String prefix = "jdbc:fake:";
private String mockPrefix = "jdbc:mock:";
private String prefix = "jdbc:fake:";
private String mockPrefix = "jdbc:mock:";
private MockExecuteHandler executeHandler = DEFAULT_HANDLER;
private MockExecuteHandler executeHandler = DEFAULT_HANDLER;
public final static MockDriver instance = new MockDriver();
public final static MockDriver instance = new MockDriver();
private final AtomicLong connectCount = new AtomicLong();
private final AtomicLong connectionCloseCount = new AtomicLong();
private final AtomicLong connectCount = new AtomicLong();
private final AtomicLong connectionCloseCount = new AtomicLong();
private final AtomicLong connectionIdSeed = new AtomicLong(1000L);
private final AtomicLong connectionIdSeed = new AtomicLong(1000L);
private final List<MockConnection> connections = new CopyOnWriteArrayList<MockConnection>();
private final List<MockConnection> connections = new CopyOnWriteArrayList<MockConnection>();
private long idleTimeCount = 1000 * 60 * 3;
private long idleTimeCount = 1000 * 60 * 3;
private boolean logExecuteQueryEnable = true;
private boolean logExecuteQueryEnable = true;
private final static String MBEAN_NAME = "com.alibaba.druid:type=MockDriver";
private final static String MBEAN_NAME = "com.alibaba.druid:type=MockDriver";
private MockConnectionFactory connectionFactory = new MockConnectionFactoryImpl();
private MockPreparedStatementFactory preparedStatementFactory = new MockPreparedStatementFactoryImpl();
static {
registerDriver(instance);
}
public MockConnectionFactory getConnectionFactory() {
return connectionFactory;
}
public void setConnectionFactory(MockConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public MockPreparedStatementFactory getPreparedStatementFactory() {
return preparedStatementFactory;
}
public void setPreparedStatementFactory(MockPreparedStatementFactory preparedStatementFactory) {
this.preparedStatementFactory = preparedStatementFactory;
}
public boolean isLogExecuteQueryEnable() {
return logExecuteQueryEnable;
}
@@ -97,11 +116,11 @@ public class MockDriver implements Driver, MockDriverMBean {
conn.close();
}
}
public int getConnectionsSize() {
return this.connections.size();
}
public List<MockConnection> getConnections() {
return connections;
}
@@ -154,7 +173,7 @@ public class MockDriver implements Driver, MockDriverMBean {
public void setExecuteHandler(MockExecuteHandler executeHandler) {
this.executeHandler = executeHandler;
}
@Override
public Connection connect(String url, Properties info) throws SQLException {
if (!acceptsURL(url)) {
@@ -173,7 +192,7 @@ public class MockDriver implements Driver, MockDriverMBean {
}
}
MockConnection conn = new MockConnection(this, url, info);
MockConnection conn = connectionFactory.createConnection(this, url, info);
if (LOG.isDebugEnabled()) {
LOG.debug("connect, url " + url + ", id " + conn.getId());
@@ -0,0 +1,6 @@
package com.alibaba.druid.mock;
public interface MockPreparedStatementFactory {
MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql);
}
@@ -0,0 +1,11 @@
package com.alibaba.druid.mock;
public class MockPreparedStatementFactoryImpl implements MockPreparedStatementFactory {
@Override
public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) {
return new MockPreparedStatement(conn, sql);
}
}
@@ -85,6 +85,7 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr
@Override
public boolean execute() throws SQLException {
updateCount = null;
lastExecuteType = StatementExecuteType.Execute;
firstResultSet = createChain().preparedStatement_execute(this);
return firstResultSet;
@@ -92,6 +93,7 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr
@Override
public ResultSet executeQuery() throws SQLException {
updateCount = null;
lastExecuteType = StatementExecuteType.ExecuteQuery;
return createChain().preparedStatement_executeQuery(this);
}
@@ -99,7 +101,8 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr
@Override
public int executeUpdate() throws SQLException {
lastExecuteType = StatementExecuteType.ExecuteUpdate;
return createChain().preparedStatement_executeUpdate(this);
updateCount = createChain().preparedStatement_executeUpdate(this);
return updateCount;
}
@Override
@@ -35,18 +35,20 @@ import com.alibaba.druid.stat.JdbcSqlStat;
*/
public class StatementProxyImpl extends WrapperProxyImpl implements StatementProxy {
private final ConnectionProxy connection;
private final Statement statement;
private final ConnectionProxy connection;
private final Statement statement;
protected String lastExecuteSql;
private long lastExecuteTimeNano;
protected JdbcSqlStat sqlStat;
protected boolean firstResultSet;
protected String lastExecuteSql;
private long lastExecuteTimeNano;
protected JdbcSqlStat sqlStat;
protected boolean firstResultSet;
protected ArrayList<String> batchSqlList;
protected ArrayList<String> batchSqlList;
protected StatementExecuteType lastExecuteType;
protected Integer updateCount = null;
public StatementProxyImpl(ConnectionProxy connection, Statement statement, long id){
super(statement, id);
this.connection = connection;
@@ -102,15 +104,17 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
@Override
public boolean execute(String sql) throws SQLException {
updateCount = null;
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.Execute;
firstResultSet = createChain().statement_execute(this, sql);
return firstResultSet;
}
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
updateCount = null;
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.Execute;
firstResultSet = createChain().statement_execute(this, sql, autoGeneratedKeys);
@@ -119,6 +123,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException {
updateCount = null;
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.Execute;
firstResultSet = createChain().statement_execute(this, sql, columnIndexes);
@@ -127,6 +132,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException {
updateCount = null;
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.Execute;
firstResultSet = createChain().statement_execute(this, sql, columnNames);
@@ -135,12 +141,19 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
@Override
public int[] executeBatch() throws SQLException {
lastExecuteType = StatementExecuteType.ExecuteBatch;
return createChain().statement_executeBatch(this);
lastExecuteType = StatementExecuteType.ExecuteBatch;
int[] updateCounts = createChain().statement_executeBatch(this);
if (updateCounts != null && updateCounts.length == 1) {
updateCount = updateCounts[0];
}
return updateCounts;
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
updateCount = null;
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.ExecuteQuery;
return createChain().statement_executeQuery(this, sql);
@@ -150,28 +163,32 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
public int executeUpdate(String sql) throws SQLException {
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.ExecuteUpdate;
return createChain().statement_executeUpdate(this, sql);
updateCount = createChain().statement_executeUpdate(this, sql);
return updateCount;
}
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.ExecuteUpdate;
return createChain().statement_executeUpdate(this, sql, autoGeneratedKeys);
updateCount = createChain().statement_executeUpdate(this, sql, autoGeneratedKeys);
return updateCount;
}
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.ExecuteUpdate;
return createChain().statement_executeUpdate(this, sql, columnIndexes);
updateCount = createChain().statement_executeUpdate(this, sql, columnIndexes);
return updateCount;
}
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
lastExecuteSql = sql;
lastExecuteType = StatementExecuteType.ExecuteUpdate;
return createChain().statement_executeUpdate(this, sql, columnNames);
updateCount = createChain().statement_executeUpdate(this, sql, columnNames);
return updateCount;
}
@Override
@@ -206,11 +223,13 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
@Override
public boolean getMoreResults() throws SQLException {
updateCount = null;
return createChain().statement_getMoreResults(this);
}
@Override
public boolean getMoreResults(int current) throws SQLException {
updateCount = null;
return createChain().statement_getMoreResults(this, current);
}
@@ -239,9 +258,13 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
return createChain().statement_getResultSetType(this);
}
//bug fixed for oracle
@Override
public int getUpdateCount() throws SQLException {
return createChain().statement_getUpdateCount(this);
if (updateCount == null) {
updateCount = createChain().statement_getUpdateCount(this);
}
return updateCount;
}
@Override
@@ -356,18 +379,18 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro
}
public long getLastExecuteTimeNano() {
return lastExecuteTimeNano;
}
return lastExecuteTimeNano;
}
public void setLastExecuteTimeNano(long lastExecuteTimeNano) {
this.lastExecuteTimeNano = lastExecuteTimeNano;
}
public void setLastExecuteTimeNano(long lastExecuteTimeNano) {
this.lastExecuteTimeNano = lastExecuteTimeNano;
}
public StatementExecuteType getLastExecuteType() {
return lastExecuteType;
}
public StatementExecuteType getLastExecuteType() {
return lastExecuteType;
}
public boolean isFirstResultSet() {
return firstResultSet;
}
public boolean isFirstResultSet() {
return firstResultSet;
}
}
@@ -0,0 +1,104 @@
package com.alibaba.druid.bvt.pool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.mock.MockConnection;
import com.alibaba.druid.mock.MockDriver;
import com.alibaba.druid.mock.MockPreparedStatement;
import com.alibaba.druid.mock.MockPreparedStatementFactory;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcUtils;
public class TestGetUpdateCount extends TestCase {
private DruidDataSource dataSource;
private MockDriver driver;
protected void setUp() throws Exception {
driver = new MockDriver();
driver.setPreparedStatementFactory(new MockPreparedStatementFactory() {
@Override
public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) {
return new MyPreparedStatement(conn, sql);
}
});
// /////////////////////////////
dataSource = new DruidDataSource();
dataSource.setDriver(driver);
dataSource.setUrl("jdbc:mock:xx");
dataSource.setFilters("stat");
}
protected void tearDown() throws Exception {
JdbcUtils.close(dataSource);
}
public void test_executeQuery() throws Exception {
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("select ?");
MyPreparedStatement myStmt = stmt.unwrap(MyPreparedStatement.class);
Assert.assertNull(myStmt.updateCount);
stmt.setString(1, "xxx");
ResultSet rs = stmt.executeQuery();
Assert.assertNull(myStmt.updateCount);
rs.close();
stmt.close();
conn.close();
}
public void test_execute() throws Exception {
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("update t set id = ?");
MyPreparedStatement myStmt = stmt.unwrap(MyPreparedStatement.class);
Assert.assertNull(myStmt.updateCount);
stmt.setString(1, "xxx");
stmt.execute();
Assert.assertNotNull(myStmt.updateCount);
Assert.assertEquals(1, stmt.getUpdateCount());
stmt.close();
conn.close();
}
public static class MyPreparedStatement extends MockPreparedStatement {
Integer updateCount = null;
public MyPreparedStatement(MockConnection conn, String sql){
super(conn, sql);
}
@Override
public int getUpdateCount() throws SQLException {
if (updateCount != null) {
throw new SQLException("illegal state");
}
updateCount = 1;
return updateCount;
}
}
}
@@ -432,6 +432,7 @@ public class PoolableStatementTest2 extends TestCase {
Statement stmt = conn.createStatement();
stmt.getUpdateCount();
stmt.executeQuery("select 1");
((DruidPooledStatement) stmt).getStatement().close();
{