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.ander...@oracle.com



Reply via email to