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