Adding field to BatchUpdateException

Lance Andersen - Oracle lance.andersen at oracle.com
Mon Nov 26 19:44:47 UTC 2012


Hi Joe,

Thank you for the sanity check.

I had added the following to the top of the javadoc (still playing with the wording):

As of Java SE 8, the method getLargeUpdateCount has been added to provide support for update counts that may be exceed Integer.MAX_VALUE and returned by the method Statement.executeLargeBatch. A JDBC driver implementation is required to throw BatchUpdateException(String reason, String SQLState, int vendorCode, long []updateCounts,Throwable cause) if an error occurs during the the execution of Statement.executeLargeBatch. If Statement.executeLargeBatch is invoked it is recommended that getLargeUpdateCounts be called instead of getUpdateCounts in order to avoid a possible overflow of the integer update count.


Best
Lance

On Nov 26, 2012, at 1:51 AM, Joe Darcy wrote:

> Hi Lance,
> 
> I don't see an obvious problem with the code, but I strongly suggest documenting the correctness conditions regarding the updateCounts and longUpdateCounts fields; I think that would ease reviewing the new constructors and serialization code.
> 
> Cheers,
> 
> -Joe
> 
> On 11/24/2012 2:05 PM, Lance Andersen - Oracle wrote:
>> Hi,
>> 
>> For JDBC 4.2, I am adding methods to allow for larger update counts (request from JDBC driver vendors)  and because of this I have to tweak BatchUpdateException
>> 
>> The Statement interface has the method
>> 
>> int[] executeBatch()
>> 
>> I am planning to add
>> 
>> long[] executeLargeBatch().
>> 
>> To accomodate this change, I  also need to add a new field and the method getLargeUpdateCount to BatchUpdateException.
>> 
>> I have exchanged emails on this with Alan and he indicated that the changes seemed reasonable but to send a general email out to see if anything was  missed from the serialization perspective.
>> 
>> I have added JDBC Unit tests to validate that the serialization/deserialization works between JDBC 4.1 and JDBC 4.2 and they run without a problem.
>> 
>> 
>> Best
>> Lance
>> 
>> new-host-2:sql lanceandersen$ diff BatchUpdateException.java ~/NetBeansProjects/JDBC4.2/jdbc4.0/src/java/sql/
>> 2c2
>> <  * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
>> ---
>>>  * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
>> 27a28,31
>>> import java.io.IOException;
>>> import java.io.InvalidObjectException;
>>> import java.io.ObjectInputStream;
>>> import java.io.ObjectOutputStream;
>> 83a88
>>>       this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);
>> 192c197
>> <         this((cause == null ? null : cause.toString()), null, 0, null, cause);
>> ---
>>>         this((cause == null ? null : cause.toString()), null, 0, (int[])null, cause);
>> 295a301
>>>         this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);
>> 331c337,401
>> <
>> ---
>>>        /**
>>>    * Constructs a <code>BatchUpdateException</code> object initialized with
>>>    * a given <code>reason</code>, <code>SQLState</code>, <code>vendorCode</code>
>>>    * <code>cause</code> and <code>updateCounts</code>.
>>>    * <p>
>>>    * This constructor should be used when the returned update count may exceed
>>>    * {@link Integer.MAX_VALUE}.
>>>    * <p>
>>>    * @param reason a description of the error
>>>    * @param SQLState an XOPEN or SQL:2003 code identifying the exception
>>>    * @param vendorCode an exception code used by a particular
>>>    * database vendor
>>>    * @param updateCounts an array of <code>long</code>, with each element
>>>    *indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
>>>    * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
>>>    * the batch for JDBC drivers that continue processing
>>>    * after a command failure; an update count or
>>>    * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
>>>    * prior to the failure for JDBC drivers that stop processing after a command
>>>    * failure
>>>    * @param cause the underlying reason for this <code>SQLException</code>
>>>    * (which is saved for later retrieval by the <code>getCause()</code> method);
>>>    * may be null indicating the cause is non-existent or unknown.
>>>    * @since 1.8
>>>    */
>>>   public BatchUpdateException(String reason, String SQLState, int vendorCode,
>>>           long []updateCounts,Throwable cause) {
>>>       super(reason, SQLState, vendorCode, cause);
>>>       this.longUpdateCounts  = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
>>>       this.updateCounts = (longUpdateCounts == null) ? null : copyUpdateCount(longUpdateCounts);
>>>   }
>>>     /**
>>>    * Retrieves the update count for each update statement in the batch
>>>    * update that executed successfully before this exception occurred.
>>>    * A driver that implements batch updates may or may not continue to
>>>    * process the remaining commands in a batch when one of the commands
>>>    * fails to execute properly. If the driver continues processing commands,
>>>    * the array returned by this method will have as many elements as
>>>    * there are commands in the batch; otherwise, it will contain an
>>>    * update count for each command that executed successfully before
>>>    * the <code>BatchUpdateException</code> was thrown.
>>>    * <p>
>>>    * This method should be used when the returned update count may exceed
>>>    * {@link Integer.MAX_VALUE}.
>>>    * <p>
>>>    * @return an array of <code>long</code> containing the update counts
>>>    * for the updates that were executed successfully before this error
>>>    * occurred.  Or, if the driver continues to process commands after an
>>>    * error, one of the following for every command in the batch:
>>>    * <OL>
>>>    * <LI>an update count
>>>    *  <LI><code>Statement.SUCCESS_NO_INFO</code> to indicate that the command
>>>    *     executed successfully but the number of rows affected is unknown
>>>    *  <LI><code>Statement.EXECUTE_FAILED</code> to indicate that the command
>>>    *     failed to execute successfully
>>>    * </OL>
>>>    * @since 1.8
>>>    */
>>>   public long[] getLargeUpdateCounts() {
>>>       return (longUpdateCounts == null) ? null :
>>>               Arrays.copyOf(longUpdateCounts, longUpdateCounts.length);
>>>   }
>>>   
>> 337c407,414
>> <   private final int[] updateCounts;
>> ---
>>>   private  int[] updateCounts;
>>> 
>>>   /**
>>>    * The array that describes the outcome of a batch execution.
>>>    * @serial
>>>    * @since 1.8
>>>    */
>>>   private  long[] longUpdateCounts;
>> 339a417,474
>>>      /*
>>>    * Utility method to copy int[] updateCount to long[] updateCount
>>>    */
>>>   private static long[] copyUpdateCount(int[] uc) {
>>>       long[] copy = new long[uc.length];
>>>       for(int i= 0; i< uc.length; i++) {
>>>           copy[i] = uc[i];
>>>                  }
>>>       return copy;
>>>   }
>>>     /*
>>>    * Utility method to copy int[] updateCount to long[] updateCount
>>>    */
>>>   private static int[] copyUpdateCount(long[] uc) {
>>>       int[] copy = new int[uc.length];
>>>       for(int i= 0; i< uc.length; i++) {
>>>           copy[i] = (int) uc[i];
>>>       }
>>>       return copy;
>>>   }
>>>     /**
>>>      * readObject is called to restore the state of the
>>>      * {@code BatchUpdateException} from a stream.
>>>      */
>>>     private void readObject(ObjectInputStream s)
>>>             throws IOException, ClassNotFoundException {
>>>                 ObjectInputStream.GetField fields = s.readFields();
>>>        int[] tmp = (int[])fields.get("updateCounts", null);
>>>        long[] tmp2 = (long[])fields.get("longUpdateCounts", null);
>>>        if(tmp != null && tmp2 != null && tmp.length != tmp2.length)
>>>            throw new InvalidObjectException("update counts are not the expected size");
>>>        if (tmp != null)
>>>            updateCounts = tmp.clone();
>>>        if (tmp2 != null)
>>>            longUpdateCounts = tmp2.clone();
>>>        if(updateCounts == null && longUpdateCounts != null)
>>>            updateCounts = copyUpdateCount(longUpdateCounts);
>>>        if(longUpdateCounts == null && updateCounts != null)
>>>            longUpdateCounts = copyUpdateCount(updateCounts);
>>> 
>>>     }
>>>          /**
>>>      * writeObject is called to save the state of the {@code BatchUpdateException}
>>>      * to a stream.
>>>      */
>>>     private void writeObject(ObjectOutputStream s)
>>>             throws IOException, ClassNotFoundException {
>>> 
>>>         ObjectOutputStream.PutField fields = s.putFields();
>>>         fields.put("updateCounts", updateCounts);
>>>         fields.put("longUpdateCounts", longUpdateCounts);
>>>         s.writeFields();
>>>     }
>> 
>> 
>> Lance Andersen| Principal Member of Technical Staff | +1.781.442.2037
>> Oracle Java Engineering
>> 1 Network Drive
>> Burlington, MA 01803
>> Lance.Andersen at oracle.com
>> 
>> 
> 

-------------- next part --------------

Lance Andersen| Principal Member of Technical Staff | +1.781.442.2037
Oracle Java Engineering 
1 Network Drive 
Burlington, MA 01803
Lance.Andersen at oracle.com



More information about the core-libs-dev mailing list