Adding field to BatchUpdateException

Joe Darcy joe.darcy at oracle.com
Tue Nov 27 08:29:28 UTC 2012


Hi Lance,

As a general comment, I would prefer release-specific information ("As 
of Java SE 8...") to appear not in javadoc, but in the non-javadoc 
comments in a class.   Such release-specific notes in the specification 
quickly become out of date.

I suggest explicitly documenting how the two fields interact in 
serialization and in live objects.  For example, can at most one be 
non-null at once, etc.

HTH,

-Joe

On 11/26/2012 11:44 AM, Lance Andersen - Oracle wrote:
> 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
>>>
>>>
>
>
> 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