Changeset: 00c6bb1d84ed for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java?cmd=changeset;node=00c6bb1d84ed
Modified Files:
        src/main/java/org/monetdb/jdbc/MonetStatement.java
Branch: default
Log Message:

Improve executeLargeBatch(). Make sure it calls getLargeUpdateCount() instead 
of getUpdateCount() to populate the long[] elements.


diffs (truncated from 315 to 300 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetStatement.java 
b/src/main/java/org/monetdb/jdbc/MonetStatement.java
--- a/src/main/java/org/monetdb/jdbc/MonetStatement.java
+++ b/src/main/java/org/monetdb/jdbc/MonetStatement.java
@@ -164,17 +164,22 @@ public class MonetStatement
         * <li>A number greater than or equal to zero -- indicates that the
         * command was processed successfully and is an update count giving
         * the number of rows in the database that were affected by the
-        * command's execution</li>
+        * command's execution
         * <li>A value of SUCCESS_NO_INFO -- indicates that the command was
-        * processed successfully but that the number of rows affected is
-        * unknown</li>
+        * processed successfully but that the number of rows affected is 
unknown
+        * <p>If one of the commands in a batch update fails to execute 
properly,
+        * this method throws a BatchUpdateException, and a JDBC driver may or
+        * may not continue to process the remaining commands in the batch.
+        * However, the driver's behavior must be consistent with a particular 
DBMS,
+        * either always continuing to process commands or never continuing to 
process
+        * commands. If the driver continues processing after a failure, the 
array
+        * returned by the method BatchUpdateException.getUpdateCounts will
+        * contain as many elements as there are commands in the batch, and at
+        * least one of the elements will be the following:</p>
+        * <li>A value of EXECUTE_FAILED -- indicates that the command failed to
+        * execute successfully and occurs only if a driver continues to process
+        * commands after a command fails
         * </ol>
-        * If one of the commands in a batch update fails to execute
-        * properly, this method throws a BatchUpdateException, and a JDBC
-        * driver may or may not continue to process the remaining commands
-        * in the batch.  However, the driver's behavior must be consistent
-        * with a particular DBMS, either always continuing to process
-        * commands or never continuing to process commands.
         *
         * MonetDB does continues after an error has occurred in the batch.
         * If one of the commands attempts to return a result set, an
@@ -184,11 +189,10 @@ public class MonetStatement
         *
         * @return an array of update counts containing one element for each
         *         command in the batch.  The elements of the array are ordered
-        *         according to the order in which commands were added to the
-        *         batch.
-        * @throws SQLException if a database access error occurs.  Throws
-        *         BatchUpdateException (a subclass of SQLException) if one of 
the
-        *         commands sent to the database fails to execute properly
+        *         according to the order in which commands were added to the 
batch.
+        * @throws SQLException if a database access error occurs.
+        * @throws BatchUpdateException (a subclass of SQLException) if one of 
the
+        *         commands sent to the database fails to execute properly.
         */
        @Override
        public int[] executeBatch() throws SQLException {
@@ -196,103 +200,13 @@ public class MonetStatement
                        return new int[0];
                }
 
-               // this method is synchronized/locked to make sure no one gets 
in between the
-               // operations we execute below
-               if (batchLock == null) {
-                       // create a ReentrantLock at first time use
-                       batchLock = new ReentrantLock();
+               final long[] ret = executeLargeBatch();
+               // copy contents of long[] into new int[]
+               final int[] counts = new int[ret.length];
+               for (int i = 0; i < ret.length; i++) {
+                       counts[i] = (ret[i] >= Integer.MAX_VALUE) ? 
Integer.MAX_VALUE : (int)ret[i];
                }
-               batchLock.lock();
-               try {
-                       final int[] counts = new int[batch.size()];
-                       final String sep = connection.queryTempl[2];
-                       final int sepLen = sep.length();
-                       final BatchUpdateException e = new 
BatchUpdateException("Error(s) occurred while executing the batch, see next 
SQLExceptions for details", "22000", counts);
-                       final StringBuilder tmpBatch = new 
StringBuilder(MapiSocket.BLOCK);
-                       int offset = 0;
-                       boolean first = true;
-                       boolean error = false;
-
-                       for (int i = 0; i < batch.size(); i++) {
-                               String tmp = batch.get(i);
-                               if (sepLen + tmp.length() > MapiSocket.BLOCK) {
-                                       // The thing is too big.  Way too big.  
Since it won't
-                                       // be optimal anyway, just add it to 
whatever we have
-                                       // and continue.
-                                       if (!first)
-                                               tmpBatch.append(sep);
-                                       tmpBatch.append(tmp);
-                                       // send and receive
-                                       error |= internalBatch(tmpBatch, 
counts, offset, i + 1, e);
-                                       offset = i;
-                                       tmpBatch.setLength(0);  // clear the 
buffer
-                                       first = true;
-                                       continue;
-                               }
-                               if (tmpBatch.length() + sepLen + tmp.length() 
>= MapiSocket.BLOCK) {
-                                       // send and receive
-                                       error |= internalBatch(tmpBatch, 
counts, offset, i + 1, e);
-                                       offset = i;
-                                       tmpBatch.setLength(0);  // clear the 
buffer
-                                       first = true;
-                               }
-                               if (first)
-                                       first = false;
-                               else
-                                       tmpBatch.append(sep);
-                               tmpBatch.append(tmp);
-                       }
-                       // send and receive
-                       error |= internalBatch(tmpBatch, counts, offset, 
counts.length, e);
-
-                       // throw BatchUpdateException if it contains something
-                       if (error)
-                               throw e;
-                       // otherwise just return the counts
-                       return counts;
-               } finally {
-                       batch.clear();
-                       batchLock.unlock();
-               }
-       }
-
-       private boolean internalBatch(
-                       final StringBuilder batch,
-                       final int[] counts,
-                       int offset,
-                       final int max,
-                       final BatchUpdateException e)
-               throws BatchUpdateException
-       {
-               try {
-                       boolean hasResultSet = 
internalExecute(batch.toString());
-                       int count = -1;
-
-                       if (!hasResultSet)
-                               count = getUpdateCount();
-
-                       do {
-                               if (offset >= max)
-                                       throw new SQLException("Overflow: don't 
use multi statements when batching (" + max + ")", "M1M16");
-                               if (hasResultSet) {
-                                       e.setNextException(
-                                               new SQLException("Batch query 
produced a ResultSet! " +
-                                                       "Ignoring and setting 
update count to " +
-                                                       "value " + 
EXECUTE_FAILED, "M1M17"));
-                                       counts[offset] = EXECUTE_FAILED;
-                               } else if (count >= 0) {
-                                       counts[offset] = count;
-                               }
-                               offset++;
-                       } while ((hasResultSet = getMoreResults()) || (count = 
getUpdateCount()) != -1);
-               } catch (SQLException ex) {
-                       e.setNextException(ex);
-                       for (; offset < max; offset++) {
-                               counts[offset] = EXECUTE_FAILED;
-                       }
-                       return true;
-               }
-               return false;
+               return counts;
        }
 
        /**
@@ -1273,10 +1187,10 @@ public class MonetStatement
         * <ol>
         * <li>A number greater than or equal to zero -- indicates that the 
command
         * was processed successfully and is an update count giving the number 
of
-        * rows in the database that were affected by the command's 
execution</li>
+        * rows in the database that were affected by the command's execution
         * <li>A value of SUCCESS_NO_INFO -- indicates that the command was
-        * processed successfully but that the number of rows affected is 
unknown</li>
-        * If one of the commands in a batch update fails to execute properly,
+        * processed successfully but that the number of rows affected is 
unknown
+        * <p>If one of the commands in a batch update fails to execute 
properly,
         * this method throws a BatchUpdateException, and a JDBC driver may or
         * may not continue to process the remaining commands in the batch.
         * However, the driver's behavior must be consistent with a particular 
DBMS,
@@ -1284,10 +1198,10 @@ public class MonetStatement
         * commands. If the driver continues processing after a failure, the 
array
         * returned by the method BatchUpdateException.getLargeUpdateCounts will
         * contain as many elements as there are commands in the batch, and at
-        * least one of the elements will be the following:
+        * least one of the elements will be the following:</p>
         * <li>A value of EXECUTE_FAILED -- indicates that the command failed to
         * execute successfully and occurs only if a driver continues to process
-        * commands after a command fails</li>
+        * commands after a command fails
         * </ol>
         *
         * This method should be used when the returned row count may exceed 
Integer.MAX_VALUE.
@@ -1304,8 +1218,9 @@ public class MonetStatement
         *      according to the order in which commands were added to the 
batch.
         * @throws SQLException if a database access error occurs, this method 
is called
         *      on a closed Statement or the driver does not support batch 
statements.
-        *      Throws BatchUpdateException (a subclass of SQLException) if one 
of the
-        *      commands sent to the database fails to execute properly or 
attempts to return a result set.
+        * @throws BatchUpdateException (a subclass of SQLException) if one of 
the
+        *      commands sent to the database fails to execute properly or
+        *      attempts to return a result set.
         */
        @Override
        public long[] executeLargeBatch() throws SQLException {
@@ -1313,15 +1228,108 @@ public class MonetStatement
                        return new long[0];
                }
 
-               final int[] ret = executeBatch();
-               // copy contents of int[] into new long[]
-               final long[] counts = new long[ret.length];
-               for (int i = 0; i < ret.length; i++) {
-                       counts[i] = ret[i];
+               // this method is synchronized/locked to make sure no one gets 
in between the
+               // operations we execute below
+               if (batchLock == null) {
+                       // create a ReentrantLock at first time use
+                       batchLock = new ReentrantLock();
                }
-               return counts;
+               batchLock.lock();
+               try {
+                       final long[] counts = new long[batch.size()];
+                       final String sep = connection.queryTempl[2];
+                       final int sepLen = sep.length();
+                       final BatchUpdateException e = new BatchUpdateException(
+                                       "Error(s) occurred while executing the 
batch, " +
+                                       "see chained SQLExceptions for 
details", "22000", 22000, counts, null);
+                       final StringBuilder tmpBatch = new 
StringBuilder(MapiSocket.BLOCK);
+                       int offset = 0;
+                       boolean first = true;
+                       boolean error = false;
+
+                       for (int i = 0; i < batch.size(); i++) {
+                               String tmp = batch.get(i);
+                               if (sepLen + tmp.length() > MapiSocket.BLOCK) {
+                                       // The thing is too big.  Way too big.  
Since it won't
+                                       // be optimal anyway, just add it to 
whatever we have
+                                       // and continue.
+                                       if (!first)
+                                               tmpBatch.append(sep);
+                                       tmpBatch.append(tmp);
+                                       // send and receive
+                                       error |= internalBatch(tmpBatch, 
counts, offset, i + 1, e);
+                                       offset = i;
+                                       tmpBatch.setLength(0);  // clear the 
buffer
+                                       first = true;
+                                       continue;
+                               }
+                               if (tmpBatch.length() + sepLen + tmp.length() 
>= MapiSocket.BLOCK) {
+                                       // send and receive
+                                       error |= internalBatch(tmpBatch, 
counts, offset, i + 1, e);
+                                       offset = i;
+                                       tmpBatch.setLength(0);  // clear the 
buffer
+                                       first = true;
+                               }
+                               if (first)
+                                       first = false;
+                               else
+                                       tmpBatch.append(sep);
+                               tmpBatch.append(tmp);
+                       }
+                       // send and receive
+                       error |= internalBatch(tmpBatch, counts, offset, 
counts.length, e);
+
+                       // throw BatchUpdateException if it contains something
+                       if (error)
+                               throw e;
+
+                       // otherwise just return the counts
+                       return counts;
+               } finally {
+                       batch.clear();
+                       batchLock.unlock();
+               }
        }
 
+       private boolean internalBatch(
+                       final StringBuilder batch,
+                       final long[] counts,
+                       int offset,
+                       final int max,
+                       final BatchUpdateException e)
+               throws BatchUpdateException
+       {
+               try {
+                       long count = -1;
+                       boolean hasResultSet = 
internalExecute(batch.toString());
+
+                       if (!hasResultSet)
+                               count = getLargeUpdateCount();
+
+                       do {
+                               if (offset >= max)
+                                       throw new SQLException("Overflow: don't 
use multi statements when batching (" + max + ")", "M1M16");
+                               if (hasResultSet) {
+                                       e.setNextException(
+                                               new SQLException("Batch query 
produced a ResultSet! " +
+                                                       "Ignoring and setting 
update count to value " + EXECUTE_FAILED, "M1M17"));
+                                       counts[offset] = EXECUTE_FAILED;
+                               } else if (count >= 0) {
+                                       counts[offset] = count;
+                               }
+                               offset++;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to