List:Commits« Previous MessageNext Message »
From:mmatthews Date:June 15 2007 1:10am
Subject:Connector/J commit: r6450 - in branches/branch_5_1/connector-j/src: com/mysql/jdbc testsuite/simple
View as plain text  
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/simplemmatthews15 Jun