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.ander...@oracle.com >> >> >
Lance Andersen| Principal Member of Technical Staff | +1.781.442.2037 Oracle Java Engineering 1 Network Drive Burlington, MA 01803 lance.ander...@oracle.com