Modified:
branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java
branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java
branches/branch_5_1/connector-j/src/testsuite/simple/CallableStatementTest.java
Log:
Setting "rewriteBatchedStatements" to "true" now causes CallableStatements
with batched arguments to be re-written in the form "CALL (...); CALL (...); ..."
to send the batch in as few client-server round trips as possible.
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java 2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java 2007-06-15 01:10:23 UTC (rev 6450)
@@ -2260,9 +2260,155 @@
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
+ if (!this.batchHasPlainStatements
+ && this.connection.getRewriteBatchedStatements()
+ && this.batchedArgs != null
+ && this.batchedArgs.size() > 3 /* cost of option setting rt-wise */) {
+ return executeBatchedCalls();
+ }
+
return super.executeBatch();
}
+ private int[] executeBatchedCalls() throws SQLException {
+ synchronized (this.connection.getMutex()) {
+ // This is kind of an abuse, but it gets the job done
+ if (this.batchedValuesClause == null) {
+ this.batchedValuesClause = this.originalSql + ";";
+ }
+
+ ConnectionImpl locallyScopedConn = this.connection;
+
+ boolean multiQueriesEnabled = locallyScopedConn.getAllowMultiQueries();
+
+ try {
+ clearWarnings();
+
+ int numBatchedArgs = this.batchedArgs.size();
+
+ if (this.retrieveGeneratedKeys) {
+ this.batchedGeneratedKeys = new ArrayList(numBatchedArgs);
+ }
+
+ int numValuesPerBatch = computeBatchSize(numBatchedArgs);
+
+ if (numBatchedArgs < numValuesPerBatch) {
+ numValuesPerBatch = numBatchedArgs;
+ }
+
+ java.sql.PreparedStatement batchedStatement = null;
+
+ int batchedParamIndex = 1;
+ int updateCountRunningTotal = 0;
+ int numberToExecuteAsMultiValue = 0;
+ int batchCounter = 0;
+
+ try {
+ if (!multiQueriesEnabled) {
+ locallyScopedConn.getIO().enableMultiQueries();
+ }
+
+ if (this.retrieveGeneratedKeys) {
+ batchedStatement = locallyScopedConn.prepareStatement(
+ generateBatchedCallSQL(numValuesPerBatch),
+ RETURN_GENERATED_KEYS);
+ } else {
+ batchedStatement = locallyScopedConn
+ .prepareStatement(generateBatchedCallSQL(numValuesPerBatch));
+ }
+
+ if (numBatchedArgs < numValuesPerBatch) {
+ numberToExecuteAsMultiValue = numBatchedArgs;
+ } else {
+ numberToExecuteAsMultiValue = numBatchedArgs / numValuesPerBatch;
+ }
+
+ int numberArgsToExecute = numberToExecuteAsMultiValue * numValuesPerBatch;
+
+ for (int i = 0; i < numberArgsToExecute; i++) {
+ if (i != 0 && i % numValuesPerBatch == 0) {
+ updateCountRunningTotal += batchedStatement.executeUpdate();
+
+ getBatchedGeneratedKeys(batchedStatement);
+ batchedStatement.clearParameters();
+ batchedParamIndex = 1;
+ }
+
+ batchedParamIndex = setOneBatchedParameterSet(batchedStatement,
+ batchedParamIndex, this.batchedArgs
+ .get(batchCounter++));
+ }
+
+ updateCountRunningTotal += batchedStatement.executeUpdate();
+ getBatchedGeneratedKeys(batchedStatement);
+
+ numValuesPerBatch = numBatchedArgs - batchCounter;
+ } finally {
+ if (batchedStatement != null) {
+ batchedStatement.close();
+ }
+ }
+
+ try {
+ if (numValuesPerBatch > 0) {
+
+ if (this.retrieveGeneratedKeys) {
+ batchedStatement = locallyScopedConn.prepareStatement(
+ generateBatchedCallSQL(numValuesPerBatch),
+ RETURN_GENERATED_KEYS);
+ } else {
+ batchedStatement = locallyScopedConn.prepareStatement(
+ generateBatchedCallSQL(numValuesPerBatch));
+ }
+
+ batchedParamIndex = 1;
+
+ while (batchCounter < numBatchedArgs) {
+ batchedParamIndex = setOneBatchedParameterSet(batchedStatement,
+ batchedParamIndex, this.batchedArgs
+ .get(batchCounter++));
+ }
+
+ updateCountRunningTotal += batchedStatement.executeUpdate();
+ getBatchedGeneratedKeys(batchedStatement);
+ }
+
+ int[] updateCounts = new int[this.batchedArgs.size()];
+
+ for (int i = 0; i < this.batchedArgs.size(); i++) {
+ updateCounts[i] = 1;
+ }
+
+ return updateCounts;
+ } finally {
+ if (batchedStatement != null) {
+ batchedStatement.close();
+ }
+ }
+ } finally {
+ if (!multiQueriesEnabled) {
+ locallyScopedConn.getIO().disableMultiQueries();
+ }
+
+ clearBatch();
+ }
+ }
+ }
+
+ private String generateBatchedCallSQL(int numBatches) {
+ StringBuffer newStatementSql = new StringBuffer((this.originalSql
+ .length() + 1) * numBatches);
+
+ newStatementSql.append(this.originalSql);
+
+ for (int i = 0; i < numBatches - 1; i++) {
+ newStatementSql.append(';');
+ newStatementSql.append(this.originalSql);
+ }
+
+ return newStatementSql.toString();
+ }
+
protected int getParameterIndexOffset() {
if (this.callingStoredFunction) {
return -1;
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2007-06-15 01:10:23 UTC (rev 6450)
@@ -490,7 +490,7 @@
protected boolean usingAnsiMode;
- private String batchedValuesClause;
+ protected String batchedValuesClause;
/** Where does the statement text actually start? */
@@ -1248,7 +1248,10 @@
// anyway
//
- sizeOfParameterSet += this.batchedValuesClause.length() + 1;
+ if (this.batchedValuesClause != null) {
+ sizeOfParameterSet += this.batchedValuesClause.length() + 1;
+ }
+
sizeOfEntireBatch += sizeOfParameterSet;
if (sizeOfParameterSet > maxSizeOfParameterSet) {
Modified: branches/branch_5_1/connector-j/src/testsuite/simple/CallableStatementTest.java
===================================================================
--- branches/branch_5_1/connector-j/src/testsuite/simple/CallableStatementTest.java 2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/testsuite/simple/CallableStatementTest.java 2007-06-15 01:10:23 UTC (rev 6450)
@@ -113,21 +113,29 @@
storedProc = this.conn.prepareCall("{call testBatch(?)}");
- storedProc.setInt(1, 1);
- storedProc.addBatch();
- storedProc.setInt(1, 2);
- storedProc.addBatch();
+ int numBatches = 300;
+
+ for (int i = 0; i < numBatches; i++) {
+ storedProc.setInt(1, i + 1);
+ storedProc.addBatch();
+ }
+
int[] counts = storedProc.executeBatch();
- assertEquals(2, counts.length);
- assertEquals(1, counts[0]);
- assertEquals(1, counts[1]);
+ assertEquals(numBatches, counts.length);
+ for (int i = 0; i < numBatches; i++) {
+ assertEquals(1, counts[i]);
+ }
+
+ /*
this.rs = this.stmt.executeQuery("SELECT field1 FROM testBatchTable ORDER BY field1 ASC");
- assertTrue(this.rs.next());
- assertEquals(1, this.rs.getInt(1));
- assertTrue(this.rs.next());
- assertEquals(2, this.rs.getInt(1));
+
+ for (int i = 0; i < numBatches; i++) {
+ assertTrue(this.rs.next());
+ assertEquals(i + 1, this.rs.getInt(1));
+ }
+ */
} finally {
if (this.rs != null) {
this.rs.close();
| Thread |
|---|
| • Connector/J commit: r6450 - in branches/branch_5_1/connector-j/src: com/mysql/jdbc testsuite/simple | mmatthews | 15 Jun |