You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2006/08/26 13:39:22 UTC
svn commit: r437146 [1/2] - in /db/derby/code/branches/10.2/java:
engine/org/apache/derby/iapi/services/io/
engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/jdbc/
testing/org/apache/derbyTesting/functionTests/master/ testing/org/apache/...
Author: kahatlen
Date: Sat Aug 26 04:39:20 2006
New Revision: 437146
URL: http://svn.apache.org/viewvc?rev=437146&view=rev
Log:
DERBY-1473: Add cut-off and truncation logic to streaming classes in
the embedded driver
Merged fix from trunk.
Added:
db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/services/io/DerbyIOException.java (with props)
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/streams/
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/streams/ByteAlphabet.java (with props)
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/streams/CharAlphabet.java (with props)
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/streams/LoopingAlphabetReader.java (with props)
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/streams/LoopingAlphabetStream.java (with props)
Modified:
db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/RawToBinaryFormatStream.java
db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java
db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SQLClob.java
db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedPreparedStatement.java
db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/characterStreams.out
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/resultsetStream.out
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/build.xml
Added: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/services/io/DerbyIOException.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/services/io/DerbyIOException.java?rev=437146&view=auto
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/services/io/DerbyIOException.java (added)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/services/io/DerbyIOException.java Sat Aug 26 04:39:20 2006
@@ -0,0 +1,56 @@
+/*
+
+ Derby - Class org.apache.derby.iapi.service.io.DerbyIOException
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.services.io;
+
+import java.io.IOException;
+
+/**
+ * A subclass of <code>IOException</code> that carries a SQL state.
+ *
+ * The original reason for adding it was to separate between
+ * <code>IOException</code>s generated by the application stream and the ones
+ * generated by the Derby wrapper streams, see for instance
+ * <code>RawToBinaryFormatStream</code>. Without this distinction, the user
+ * would not be able to easily write <code>catch</code>-blocks to handle
+ * specific errors happening when reading streams.
+ */
+public final class DerbyIOException
+ extends IOException {
+
+ /** A Derby SQLState. */
+ private final String sqlState;
+
+ /**
+ * Create a new Derby IO exception.
+ *
+ * @param msg a string describing the error
+ * @param sqlState a Derby SQLState describing the error
+ */
+ public DerbyIOException(String msg, String sqlState) {
+ super(msg);
+ this.sqlState = sqlState;
+ }
+
+ public String getSQLState() {
+ return sqlState;
+ }
+} // End class DerbyIOException
Propchange: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/services/io/DerbyIOException.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/RawToBinaryFormatStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/RawToBinaryFormatStream.java?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/RawToBinaryFormatStream.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/RawToBinaryFormatStream.java Sat Aug 26 04:39:20 2006
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.EOFException;
+import org.apache.derby.iapi.services.io.DerbyIOException;
import org.apache.derby.iapi.services.io.LimitInputStream;
import org.apache.derby.iapi.services.i18n.MessageService;
import org.apache.derby.iapi.reference.SQLState;
@@ -64,44 +65,103 @@
// and eof reached
private boolean eof = false;
- /**
- @param in Application's raw binary stream passed into JDBC layer
- @param length - length of the stream, if known, otherwise -1.
- */
- public RawToBinaryFormatStream(InputStream in, int length) {
- super(in);
+ /**
+ * The length of the stream.
+ * Unknown if less than 0.
+ */
+ private final int length;
+ /**
+ * The maximum allowed length for the stream.
+ * No limit if less than 0.
+ */
+ private final int maximumLength;
+ /**
+ * The type of the column the stream is inserted into.
+ * Used for length less streams, <code>null</code> if not in use.
+ */
+ private final String typeName;
- if (length >= 0) {
- setLimit(length);
-
- if (length <= 31)
- {
- encodedLength = new byte[1];
- encodedLength[0] = (byte) (0x80 | (length & 0xff));
- }
- else if (length <= 0xFFFF)
- {
- encodedLength = new byte[3];
- encodedLength[0] = (byte) 0xA0;
- encodedLength[1] = (byte)(length >> 8);
- encodedLength[2] = (byte)(length);
- }
- else
- {
- encodedLength = new byte[5];
- encodedLength[0] = (byte) 0xC0;
- encodedLength[1] = (byte)(length >> 24);
- encodedLength[2] = (byte)(length >> 16);
- encodedLength[3] = (byte)(length >> 8);
- encodedLength[4] = (byte)(length);
- }
- }
+ /**
+ * Create a binary on-disk stream from the given <code>InputStream</code>.
+ *
+ * The on-disk stream prepends a length encoding, and validates that the
+ * actual length of the stream matches the specified length (as according
+ * to JDBC 3.0).
+ *
+ * @param in application's raw binary stream passed into JDBC layer
+ * @param length length of the stream
+ * @throws IllegalArgumentException if <code>length</code> is negative.
+ * This exception should never be exposed to the user, and seeing it
+ * means a programming error exists in the code.
+ */
+ public RawToBinaryFormatStream(InputStream in, int length) {
+ super(in);
+ if (length < 0) {
+ throw new IllegalArgumentException(
+ "Stream length cannot be negative: " + length);
+ }
+ this.length = length;
+ this.maximumLength = -1;
+ this.typeName = null;
+
+ setLimit(length);
+
+ if (length <= 31)
+ {
+ encodedLength = new byte[1];
+ encodedLength[0] = (byte) (0x80 | (length & 0xff));
+ }
+ else if (length <= 0xFFFF)
+ {
+ encodedLength = new byte[3];
+ encodedLength[0] = (byte) 0xA0;
+ encodedLength[1] = (byte)(length >> 8);
+ encodedLength[2] = (byte)(length);
+ }
else
{
- // unknown length, four zero bytes
- encodedLength = new byte[4];
+ encodedLength = new byte[5];
+ encodedLength[0] = (byte) 0xC0;
+ encodedLength[1] = (byte)(length >> 24);
+ encodedLength[2] = (byte)(length >> 16);
+ encodedLength[3] = (byte)(length >> 8);
+ encodedLength[4] = (byte)(length);
}
- }
+ }
+
+ /**
+ * Create a binary on-disk stream from the given <code>InputStream</code>
+ * of unknown length.
+ *
+ * A limit is placed on the maximum length of the stream.
+ *
+ * @param in the application stream
+ * @param maximumLength maximum length of the column data is inserted into
+ * @param typeName type name for the column data is inserted into
+ * @throws IllegalArgumentException if maximum length is negative, or type
+ * name is <code>null<code>. This exception should never be exposed
+ * to the user, and seeing it means a programming error exists in the
+ * code. Although a missing type name is not critical, an exception is
+ * is thrown to signal the intended use of this constructor.
+ */
+ public RawToBinaryFormatStream(InputStream in,
+ int maximumLength,
+ String typeName) {
+ super(in);
+ if (maximumLength < 0) {
+ throw new IllegalArgumentException("Maximum length for a capped " +
+ "stream cannot be negative: " + maximumLength);
+ }
+ if (typeName == null) {
+ throw new IllegalArgumentException("Type name cannot be null");
+ }
+ this.length = -1;
+ this.maximumLength = maximumLength;
+ this.typeName = typeName;
+ // Unknown length, four zero bytes.
+ encodedLength = new byte[4];
+ setLimit(maximumLength);
+ }
/**
Read from the wrapped stream prepending the intial bytes if needed.
@@ -143,8 +203,12 @@
int remainingBytes = clearLimit();
- if (remainingBytes > 0)
- throw new IOException(MessageService.getTextMessage(SQLState.SET_STREAM_INEXACT_LENGTH_DATA));
+ if (length > -1 && remainingBytes > 0) {
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA),
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA);
+ }
// if we had a limit try reading one more byte.
// JDBC 3.0 states the stream muct have the correct number of characters in it.
@@ -157,8 +221,25 @@
catch (IOException ioe) {
c = -1;
}
- if (c != -1)
- throw new IOException(MessageService.getTextMessage(SQLState.SET_STREAM_INEXACT_LENGTH_DATA));
+ if (c != -1) {
+ if (length > -1) {
+ // Stream is not capped, and should have matched the
+ // specified length.
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA),
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA);
+ } else {
+ // Stream is capped, and has exceeded the maximum length.
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.LANG_STRING_TRUNCATION,
+ typeName,
+ "XXXX",
+ String.valueOf(maximumLength)),
+ SQLState.LANG_STRING_TRUNCATION);
+ }
+ }
}
}
Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java Sat Aug 26 04:39:20 2006
@@ -28,8 +28,9 @@
import java.io.UTFDataFormatException;
import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.services.i18n.MessageService;
+import org.apache.derby.iapi.services.io.DerbyIOException;
import org.apache.derby.iapi.services.io.LimitReader;
-import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.types.TypeId;
/**
Converts a java.io.Reader to the on-disk UTF8 format used by Derby
@@ -38,8 +39,6 @@
public final class ReaderToUTF8Stream
extends InputStream
{
- public static final int UNKNOWN_LENGTH = Integer.MIN_VALUE;
-
/**
* Application's reader wrapped in a LimitReader.
*/
@@ -59,8 +58,8 @@
for clobs,varchar,char.
If zero, no characters are truncated.
*/
- private int charsToTruncate;
- private static final char SPACE =' ';
+ private final int charsToTruncate;
+ private static final char SPACE = ' ';
/**
* Length of the final value, after truncation if any,
@@ -70,27 +69,71 @@
information about the column width.
*/
private final int valueLength;
+ /** The maximum allowed length of the stream. */
+ private final int maximumLength;
+ /** The type name for the column data is inserted into. */
+ private final String typeName;
/**
- * Create a stream with truncation.
+ * Create a stream that will truncate trailing blanks if required/allowed.
+ *
+ * If the stream must be truncated, the number of blanks to truncate
+ * is specified to allow the stream to be checked for exact length, as
+ * required by JDBC 3.0. If the stream is shorter or longer than specified,
+ * an exception is thrown during read.
+ *
+ * @param appReader application reader
+ * @param valueLength the length of the reader in characters
+ * @param numCharsToTruncate the number of trailing blanks to truncate
+ * @param typeName type name of the column data is inserted into
*/
- public ReaderToUTF8Stream(Reader appReader, int valueLength,int numCharsToTruncate)
- {
+ public ReaderToUTF8Stream(Reader appReader,
+ int valueLength,
+ int numCharsToTruncate,
+ String typeName) {
this.reader = new LimitReader(appReader);
- if (valueLength != UNKNOWN_LENGTH) {
- reader.setLimit(valueLength);
- }
- if (SanityManager.DEBUG && valueLength == UNKNOWN_LENGTH) {
- // Number of chars to truncate must be 0 if length is unknown.
- // This count is used to check if the stream matches the
- // specified length.
- SanityManager.ASSERT(numCharsToTruncate == 0);
- }
+ reader.setLimit(valueLength);
buffer = new byte[BUFSIZE];
blen = -1;
this.charsToTruncate = numCharsToTruncate;
this.valueLength = valueLength;
- }
+ this.maximumLength = -1;
+ this.typeName = typeName;
+ }
+
+ /**
+ * Create a UTF-8 stream for a length less application reader.
+ *
+ * A limit is placed on the length of the reader. If the reader exceeds
+ * the maximum length, truncation of trailing blanks is attempted. If
+ * truncation fails, an exception is thrown.
+ *
+ * @param appReader application reader
+ * @param maximumLength maximum allowed length in number of characters for
+ * the reader
+ * @param typeName type name of the column data is inserted into
+ * @throws IllegalArgumentException if maximum length is negative, or type
+ * name is <code>null<code>
+ */
+ public ReaderToUTF8Stream(Reader appReader,
+ int maximumLength,
+ String typeName) {
+ if (maximumLength < 0) {
+ throw new IllegalArgumentException("Maximum length for a capped " +
+ "stream cannot be negative: " + maximumLength);
+ }
+ if (typeName == null) {
+ throw new IllegalArgumentException("Type name cannot be null");
+ }
+ this.reader = new LimitReader(appReader);
+ reader.setLimit(maximumLength);
+ buffer = new byte[BUFSIZE];
+ blen = -1;
+ this.maximumLength = maximumLength;
+ this.typeName = typeName;
+ this.charsToTruncate = -1;
+ this.valueLength = -1;
+ }
/**
* read from stream; characters converted to utf-8 derby specific encoding.
@@ -228,11 +271,19 @@
checkSufficientData();
}
- /**
- JDBC 3.0 (from tutorial book) requires that an
- input stream has the correct number of bytes in
- the stream.
- */
+ /**
+ * Validate the length of the stream, take corrective action if allowed.
+ *
+ * JDBC 3.0 (from tutorial book) requires that an input stream has the
+ * correct number of bytes in the stream.
+ * If the stream is too long, trailing blank truncation is attempted if
+ * allowed. If truncation fails, or is disallowed, an exception is thrown.
+ *
+ * @throws IOException if an errors occurs in the application stream
+ * @throws DerbyIOException if Derby finds a problem with the stream;
+ * stream is too long and cannot be truncated, or the stream length
+ * does not match the specified length
+ */
private void checkSufficientData() throws IOException
{
// now that we finished reading from the stream; the amount
@@ -240,54 +291,41 @@
if (charsToTruncate > 0)
{
reader.setLimit(charsToTruncate);
- int c = 0;
- for (;;)
- {
- c = reader.read();
-
- if (c < 0)
- {
- break;
- }
- else if (c != SPACE)
- {
- // [NOTE] The assumption that this is always a Clob is not
- // enforced anywhere (i.e. that 'charsToTruncate'
- // is 0 for all other types)
- // throw truncation error, wont happen here for any other
- // type except for clob
- // hence using TypeId.CLOB_NAME to avoid having to store
- // the type information along with this stream.
- throw new IOException(
- MessageService.getTextMessage(
- SQLState.LANG_STRING_TRUNCATION,
- TypeId.CLOB_NAME,
- "XXXX",
- String.valueOf(valueLength)));
- }
- }
+ truncate();
}
+ // A length less stream that is capped, will return 0 even if there
+ // are more bytes in the application stream.
int remainingBytes = reader.clearLimit();
- if (remainingBytes > 0)
- throw new IOException(MessageService.getTextMessage(SQLState.SET_STREAM_INEXACT_LENGTH_DATA));
+ if (remainingBytes > 0 && valueLength > 0) {
+ // If we had a specified length, throw exception.
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA),
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA);
+ }
// if we had a limit try reading one more character.
- // JDBC 3.0 states the stream muct have the correct number of
+ // JDBC 3.0 states the stream must have the correct number of
// characters in it.
-
- if (remainingBytes == 0) {
- int c;
- try
- {
- c = reader.read();
-
- }
- catch (IOException ioe) {
- c = -1;
- }
- if (c >= 0)
- throw new IOException(MessageService.getTextMessage(SQLState.SET_STREAM_INEXACT_LENGTH_DATA));
+ if (remainingBytes == 0 && reader.read() >= 0) {
+ if (valueLength > -1) {
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA),
+ SQLState.SET_STREAM_INEXACT_LENGTH_DATA);
+ } else {
+ // Stream was capped (length less) and too long.
+ // Try to truncate if allowed, or else throw exception.
+ if (canTruncate()) {
+ truncate();
+ } else {
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.LANG_STRING_TRUNCATION),
+ SQLState.LANG_STRING_TRUNCATION);
+ }
+ }
}
// can put the correct length into the stream.
@@ -306,6 +344,42 @@
buffer[blen++] = (byte) 0x00;
}
}
+
+ /**
+ * Determine if trailing blank truncation is allowed.
+ */
+ private boolean canTruncate() {
+ // Only a few types can be truncated, default is to not allow.
+ if (typeName.equals(TypeId.CLOB_NAME)) {
+ return true;
+ } else if (typeName.equals(TypeId.VARCHAR_NAME)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempt to truncate the stream by removing trailing blanks.
+ */
+ private void truncate()
+ throws IOException {
+ int c = 0;
+ for (;;) {
+ c = reader.read();
+
+ if (c < 0) {
+ break;
+ } else if (c != SPACE) {
+ throw new DerbyIOException(
+ MessageService.getTextMessage(
+ SQLState.LANG_STRING_TRUNCATION,
+ typeName,
+ "XXXX",
+ String.valueOf(valueLength)),
+ SQLState.LANG_STRING_TRUNCATION);
+ }
+ }
+ }
/**
* return resources
Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SQLClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SQLClob.java?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SQLClob.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SQLClob.java Sat Aug 26 04:39:20 2006
@@ -317,7 +317,7 @@
throw this.outOfRange();
setValue(new ReaderToUTF8Stream(vc.getCharacterStream(),
- (int) vcl, 0), (int) vcl);
+ (int) vcl, 0, TypeId.CLOB_NAME), (int) vcl);
} catch (SQLException e) {
throw dataTypeConversion("DAN-438-tmp");
Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedPreparedStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedPreparedStatement.java?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedPreparedStatement.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedPreparedStatement.java Sat Aug 26 04:39:20 2006
@@ -733,8 +733,7 @@
*/
if (!lengthLess && length > Integer.MAX_VALUE)
throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
- preparedStatement.getParameterTypes()
- [parameterIndex-1].getSQLstring());
+ getParameterSQLType(parameterIndex));
try {
ReaderToUTF8Stream utfIn;
@@ -784,19 +783,19 @@
}
}
// Create a stream with truncation.
- utfIn = new ReaderToUTF8Stream(reader,
- usableLength,
- truncationLength);
+ utfIn = new ReaderToUTF8Stream(reader, usableLength,
+ truncationLength, getParameterSQLType(parameterIndex));
} else {
- // Create a stream without exactness checks and truncation.
- utfIn = new ReaderToUTF8Stream(reader,
- ReaderToUTF8Stream.UNKNOWN_LENGTH,
- 0);
+ // Create a stream without exactness checks,
+ // but with a maximum limit.
+ utfIn = new ReaderToUTF8Stream(reader, colWidth,
+ getParameterSQLType(parameterIndex));
}
// JDBC is one-based, DBMS is zero-based.
// Note that for lengthless stream, usableLength will be
- // Integer.MIN_VALUE. This is okay, based on the observation that
+ // the maximum length for the column.
+ // This is okay, based on the observation that
// setValue does not use the value for anything at all.
pvs.getParameterForSet(
parameterIndex - 1).setValue(utfIn, usableLength);
@@ -898,13 +897,20 @@
}
try {
- // If stream is lengthless, force length to -1 to get the expected
- // behavior in RawToBinaryFormatStream.
+ RawToBinaryFormatStream rawStream;
if (lengthLess) {
+ // Force length to -1 for good measure.
length = -1;
+ DataTypeDescriptor dtd[] =
+ preparedStatement.getParameterTypes();
+ rawStream = new RawToBinaryFormatStream(x,
+ dtd[parameterIndex -1].getMaximumWidth(),
+ dtd[parameterIndex -1].getTypeName());
+ } else {
+ rawStream = new RawToBinaryFormatStream(x, (int)length);
}
getParms().getParameterForSet(parameterIndex - 1).setValue(
- new RawToBinaryFormatStream(x, (int)length), (int)length);
+ rawStream, (int)length);
} catch (StandardException t) {
throw EmbedResultSet.noStateChangeException(t);
@@ -1503,6 +1509,19 @@
return type;
}
+
+ /**
+ * Return the SQL type name for the parameter.
+ *
+ * @param parameterIndex the 1-based index of the parameter
+ * @return SQL name of the parameter
+ * @throws SQLException if parameter is out of range
+ */
+ protected final String getParameterSQLType(int parameterIndex)
+ throws SQLException {
+ DataTypeDescriptor[] pTypes = getTypes(parameterIndex);
+ return pTypes[parameterIndex-1].getTypeName();
+ }
/**
* Set the scale of a parameter.
Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Sat Aug 26 04:39:20 2006
@@ -2846,6 +2846,7 @@
private void updateBinaryStreamInternal(int columnIndex, InputStream x,
final boolean lengthLess, long length, String updateMethodName)
throws SQLException {
+ RawToBinaryFormatStream rawStream;
if (!lengthLess) {
if (length < 0)
throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
@@ -2857,14 +2858,18 @@
throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
getColumnSQLType(columnIndex));
}
+ rawStream = new RawToBinaryFormatStream(x, (int)length);
} else {
// Force length to -1 if stream is length less.
length = -1;
+ rawStream = new RawToBinaryFormatStream(x,
+ getMaxColumnWidth(columnIndex),
+ getColumnSQLType(columnIndex));
}
try {
getDVDforColumnToBeUpdated(columnIndex, updateMethodName).setValue(
- new RawToBinaryFormatStream(x, (int) length), (int) length);
+ rawStream, (int) length);
} catch (StandardException t) {
throw noStateChangeException(t);
}
@@ -2987,8 +2992,7 @@
if (getColumnType(columnIndex) == Types.CLOB) {
// Need column width to figure out if truncation is
// needed
- int colWidth = resultDescription.getColumnDescriptor(
- columnIndex).getType().getMaximumWidth();
+ int colWidth = getMaxColumnWidth(columnIndex);
// It is possible that the length of the stream passed in
// is greater than the column width, in which case the data
@@ -3002,13 +3006,16 @@
}
}
- utfIn = new ReaderToUTF8Stream(
- reader, usableLength, truncationLength);
+ utfIn = new ReaderToUTF8Stream(reader, usableLength,
+ truncationLength, getColumnSQLType(columnIndex));
} else {
+ int colWidth = getMaxColumnWidth(columnIndex);
utfIn = new ReaderToUTF8Stream(
- reader, ReaderToUTF8Stream.UNKNOWN_LENGTH, 0);
+ reader, colWidth, getColumnSQLType(columnIndex));
}
+ // NOTE: The length argument to setValue is not used. If that
+ // changes, the value might also have to change.
getDVDforColumnToBeUpdated(columnIndex, updateMethodName).setValue(
utfIn, (int) usableLength);
} catch (StandardException t) {
@@ -4514,6 +4521,20 @@
{
return resultDescription.getColumnDescriptor(column)
.getType().getTypeId().getSQLTypeName();
+ }
+
+ /**
+ * Return the user-defined maximum size of the column.
+ *
+ * Note that this may be different from the maximum column size Derby is
+ * able, or allowed, to handle (called 'maximum maximum length').
+ *
+ * @param columnIndex the 1-based index of the column
+ * @return the maximum length of the column
+ */
+ private final int getMaxColumnWidth(int columnIndex) {
+ return resultDescription.getColumnDescriptor(columnIndex).
+ getType().getMaximumWidth();
}
private final SQLException dataTypeConversion(String targetType, int column) {
Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/characterStreams.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/characterStreams.out?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/characterStreams.out (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/characterStreams.out Sat Aug 26 04:39:20 2006
@@ -4,11 +4,11 @@
MORE BYTES IN STREAM THAN PASSED IN VALUE
MORE BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS BYTES IN STREAM THAN PASSED IN VALUE
LESS BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
NULL ASCII STREAM
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
@@ -28,11 +28,11 @@
MORE BYTES IN STREAM THAN PASSED IN VALUE
MORE BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS BYTES IN STREAM THAN PASSED IN VALUE
LESS BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
NULL ASCII STREAM
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
@@ -52,11 +52,11 @@
MORE BYTES IN STREAM THAN PASSED IN VALUE
MORE BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS BYTES IN STREAM THAN PASSED IN VALUE
LESS BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
NULL ASCII STREAM
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
@@ -74,10 +74,10 @@
Test setCharacterStream into CHAR
MORE CHARACTERS IN READER THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS CHARACTERS IN READER STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
13 |A Mississippi Republican |24 |NULL |NULL |NULL |NULL
@@ -86,10 +86,10 @@
Test setCharacterStream into VARCHAR
MORE CHARACTERS IN READER THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS CHARACTERS IN READER STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
18 |NULL |NULL |A Mississippi Republican |24 |NULL |NULL
@@ -98,10 +98,10 @@
Test setCharacterStream into LONG VARCHAR
MORE CHARACTERS IN READER THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS CHARACTERS IN READER STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
23 |NULL |NULL |NULL |NULL |A Mississippi Republican |24
@@ -187,11 +187,11 @@
MORE BYTES IN STREAM THAN PASSED IN VALUE
MORE BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS BYTES IN STREAM THAN PASSED IN VALUE
LESS BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
NULL ASCII STREAM
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
@@ -211,11 +211,11 @@
MORE BYTES IN STREAM THAN PASSED IN VALUE
MORE BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS BYTES IN STREAM THAN PASSED IN VALUE
LESS BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
NULL ASCII STREAM
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
@@ -235,11 +235,11 @@
MORE BYTES IN STREAM THAN PASSED IN VALUE
MORE BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XSDA4) An unexpected exception was thrown
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS BYTES IN STREAM THAN PASSED IN VALUE
LESS BYTES IN ASCII STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XSDA4) An unexpected exception was thrown
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
NULL ASCII STREAM
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
@@ -257,10 +257,10 @@
Test setCharacterStream into CHAR
MORE CHARACTERS IN READER THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS CHARACTERS IN READER STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
13 |A Mississippi Republican |24 |NULL |NULL |NULL |NULL
@@ -269,10 +269,10 @@
Test setCharacterStream into VARCHAR
MORE CHARACTERS IN READER THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS CHARACTERS IN READER STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XCL30) An IOException was thrown when reading a 'java.sql.String' from an InputStream.
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
18 |NULL |NULL |A Mississippi Republican |24 |NULL |NULL
@@ -281,10 +281,10 @@
Test setCharacterStream into CLOB
MORE CHARACTERS IN READER THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XSDA4) An unexpected exception was thrown
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
LESS CHARACTERS IN READER STREAM THAN SPECIFIED LENGTH - REJECTED
EXPECTED SQL Exception: (XSDA4) An unexpected exception was thrown
-EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQL Exception: (XJ001) Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
ID |C |CLEN |VC |VCLEN |LVC |LVCLEN
-----------------------------------------------------------------------------------------------------------------------------
23 |NULL |NULL |NULL |NULL |A Mississippi Republican |24
Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/resultsetStream.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/resultsetStream.out?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/resultsetStream.out (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/resultsetStream.out Sat Aug 26 04:39:20 2006
@@ -10,9 +10,9 @@
len=56
number of reads=56
EXPECTED SQLSTATE(XSDA4): An unexpected exception was thrown
-EXPECTED SQLSTATE(XJ001): Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQLSTATE(XJ001): Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
EXPECTED SQLSTATE(XSDA4): An unexpected exception was thrown
-EXPECTED SQLSTATE(XJ001): Java exception: 'Input stream did not have exact amount of data as the requested length.: java.io.IOException'.
+EXPECTED SQLSTATE(XJ001): Java exception: 'Input stream did not have exact amount of data as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
Test of getAsciiStream
U+0041U+0042U+0043U+0044U+0045U+0046U+0047U+00c0U+00c1U+00c2U+00c3U+00c4U+00c5U+00ffU+003fU+003fU+003fU+003fU+003fU+003f
U+0041U+0042U+0043U+0044U+0045U+0046U+0047U+00c0U+00c1U+00c2U+00c3U+00c4U+00c5U+00ffU+0100U+3042U+3044U+3046U+3048U+304a
Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out Sat Aug 26 04:39:20 2006
@@ -111,10 +111,10 @@
No truncation and hence no error.
===> testing(using setAsciiStream) extin/char32675.data length = 32675
EXPECTED SQLSTATE(XSDA4): An unexpected exception was thrown
-EXPECTED SQLSTATE(XJ001): Java exception: 'A truncation error was encountered trying to shrink CLOB 'XXXX' to length 32672.: java.io.IOException'.
+EXPECTED SQLSTATE(XJ001): Java exception: 'A truncation error was encountered trying to shrink CLOB 'XXXX' to length 32672.: org.apache.derby.iapi.services.io.DerbyIOException'.
===> testing(using setCharacterStream) extin/char32675.data length = 32675
EXPECTED SQLSTATE(XSDA4): An unexpected exception was thrown
-EXPECTED SQLSTATE(XJ001): Java exception: 'A truncation error was encountered trying to shrink CLOB 'XXXX' to length 32672.: java.io.IOException'.
+EXPECTED SQLSTATE(XJ001): Java exception: 'A truncation error was encountered trying to shrink CLOB 'XXXX' to length 32672.: org.apache.derby.iapi.services.io.DerbyIOException'.
===> testing trailing non-blanks(using setString) length = 32675
expected exception for data > 32672 in length
===> testing trailing non-blanks(using setObject) length = 32675
Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java Sat Aug 26 04:39:20 2006
@@ -24,32 +24,70 @@
import junit.framework.*;
import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.BaseJDBCTestSetup;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
import java.io.*;
import java.sql.*;
import javax.sql.*;
+import org.apache.derby.iapi.services.io.DerbyIOException;
+import org.apache.derby.impl.jdbc.EmbedSQLException;
+
/**
* This class is used to test JDBC4 specific methods in the PreparedStatement(s)
* object.
+ *
+ * A number of methods and variables are in place to aid the writing of tests:
+ * <ul><li>setBinaryStreamOnBlob
+ * <li>setAsciiStream
+ * <li>key - an id. One is generated each time setUp is run.
+ * <li>reqeustKey() - generate a new unique id.
+ * <li>psInsertX - prepared statements for insert.
+ * <li>psFetchX - prepared statements for fetching values.
+ * </ul>
+ *
+ * For table creation, see the <code>suite</code>-method.
*/
public class PreparedStatementTest extends BaseJDBCTestCase {
+ private static final String BLOBTBL = "BlobTestTable";
+ private static final String CLOBTBL = "ClobTestTable";
+ private static final String LONGVARCHAR = "LongVarcharTestTable";
+
+ /** Key used to id data inserted into the database. */
+ private static int globalKey = 1;
+
/** Byte array passed in to the database. **/
private static final byte[] BYTES = {
0x65, 0x66, 0x67, 0x68, 0x69,
0x69, 0x68, 0x67, 0x66, 0x65
};
- /**
- * Default connection and prepared statements that are used by the tests.
+ // Default connection and prepared statements that are used by the tests.
+ /**
+ * Default key to use for insertions.
+ * Is unique for each fixture. More keys can be fetched by calling
+ * <link>requestKey</link>.
*/
- //Connection object
- //PreparedStatement object
+ private int key;
+ /** Default connection object. */
+ /** PreparedStatement object with no positional arguments. */
private PreparedStatement ps = null;
+ /** PreparedStatement to fetch BLOB with specified id. */
+ private PreparedStatement psFetchBlob = null;
+ /** PreparedStatement to insert a BLOB with specified id. */
+ private PreparedStatement psInsertBlob = null;
+ /** PreparedStatement to fetch CLOB with specified id. */
+ private PreparedStatement psFetchClob = null;
+ /** PreparedStatement to insert a CLOB with specified id. */
+ private PreparedStatement psInsertClob = null;
+ /** PreparedStatement to insert a LONG VARCHAR with specified id. */
+ private PreparedStatement psInsertLongVarchar = null;
//Statement object
private Statement s = null;
+
/**
* Create a test with the given name.
@@ -69,7 +107,8 @@
*/
public void setUp()
throws SQLException {
- //create the statement object
+ key = requestKey();
+ //create the statement object
s = createStatement();
//Create the PreparedStatement that will then be used as the basis
//throughout this test henceforth
@@ -77,14 +116,17 @@
//setClob and setBlob
ps = prepareStatement("select count(*) from sys.systables");
- // STEP1: create the tables
- // Structure of table
- // --------------------------
- // SNO Clob Column
- // --------------------------
-
- s.execute("create table ClobTestTable (sno int, clobCol CLOB(1M))");
- s.execute("create table BlobTestTable (sno int, blobCol BLOB(1M))");
+ // Prepare misc statements.
+ psFetchBlob = prepareStatement("SELECT dBlob FROM " +
+ BLOBTBL + " WHERE sno = ?");
+ psInsertBlob = prepareStatement("INSERT INTO " + BLOBTBL +
+ " VALUES (?, ?)");
+ psFetchClob = prepareStatement("SELECT dClob FROM " +
+ CLOBTBL + " WHERE sno = ?");
+ psInsertClob = prepareStatement("INSERT INTO " + CLOBTBL +
+ " VALUES (?, ?)");
+ psInsertLongVarchar = prepareStatement("INSERT INTO " + LONGVARCHAR +
+ " VALUES (?, ?)");
}
/**
@@ -97,9 +139,11 @@
public void tearDown()
throws Exception {
- s.execute("drop table ClobTestTable");
- s.execute("drop table BlobTestTable");
- s.close();
+ psFetchBlob.close();
+ psFetchClob.close();
+ psInsertBlob.close();
+ psInsertClob.close();
+ psInsertLongVarchar.close();
super.tearDown();
}
@@ -108,7 +152,48 @@
TestSuite suite = new TestSuite();
suite.addTestSuite(PreparedStatementTest.class);
suite.addTest(SetObjectUnsupportedTest.suite(false));
- return suite;
+ return new BaseJDBCTestSetup(suite) {
+ public void setUp()
+ throws java.lang.Exception {
+ try {
+ create();
+ } catch (SQLException sqle) {
+ if (sqle.getSQLState().equals("X0Y32")) {
+ drop();
+ create();
+ } else {
+ throw sqle;
+ }
+ }
+ }
+
+ public void tearDown()
+ throws java.lang.Exception {
+ drop();
+ super.tearDown();
+ }
+
+ private void create()
+ throws SQLException {
+ Statement stmt = getConnection().createStatement();
+ stmt.execute("create table " + BLOBTBL +
+ " (sno int, dBlob BLOB(1M))");
+ stmt.execute("create table " + CLOBTBL +
+ " (sno int, dClob CLOB(1M))");
+ stmt.execute("create table " + LONGVARCHAR +
+ " (sno int, dLongVarchar LONG VARCHAR)");
+ stmt.close();
+ }
+
+ private void drop()
+ throws SQLException {
+ Statement stmt = getConnection().createStatement();
+ stmt.execute("drop table " + BLOBTBL);
+ stmt.execute("drop table " + CLOBTBL);
+ stmt.execute("drop table " + LONGVARCHAR);
+ stmt.close();
+ }
+ };
}
//--------------------------------------------------------------------------
@@ -321,30 +406,31 @@
StringReader is = new StringReader("Test data for the Clob object");
is.reset();
- PreparedStatement ps_sc = prepareStatement("insert into ClobTestTable values(?,?)");
-
//initially insert the data
- ps_sc.setInt(1,1);
- ps_sc.setClob(2,is,str.length());
- ps_sc.executeUpdate();
+ psInsertClob.setInt(1, key);
+ psInsertClob.setClob(2, is, str.length());
+ psInsertClob.executeUpdate();
//Now query to retrieve the Clob
- ResultSet rs = s.executeQuery("select * from ClobTestTable where sno = 1");
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
rs.next();
- Clob clobToBeInserted = rs.getClob(2);
+ Clob clobToBeInserted = rs.getClob(1);
rs.close();
//Now use the setClob method
- ps_sc.setInt(1,2);
- ps_sc.setClob(2,clobToBeInserted);
- ps_sc.execute();
+ int secondKey = requestKey();
+ psInsertClob.setInt(1, secondKey);
+ psInsertClob.setClob(2, clobToBeInserted);
+ psInsertClob.execute();
- ps_sc.close();
+ psInsertClob.close();
//Now test to see that the Clob has been stored correctly
- rs = s.executeQuery("select * from ClobTestTable where sno = 2");
+ psFetchClob.setInt(1, secondKey);
+ rs = psFetchClob.executeQuery();
rs.next();
- Clob clobRetrieved = rs.getClob(2);
+ Clob clobRetrieved = rs.getClob(1);
assertEquals(clobToBeInserted,clobRetrieved);
}
@@ -363,25 +449,24 @@
// Insert test data.
String testString = "Test string for setCharacterStream\u1A00";
Reader reader = new StringReader(testString);
- PreparedStatement psChar = prepareStatement(
- "insert into ClobTestTable values (?,?)");
- psChar.setInt(1, 1);
- psChar.setCharacterStream(2, reader);
- psChar.execute();
+ psInsertClob.setInt(1, key);
+ psInsertClob.setCharacterStream(2, reader);
+ psInsertClob.execute();
reader.close();
// Must fetch Clob from database because we don't support
// Connection.createClob on the client yet.
- ResultSet rs = s.executeQuery(
- "select clobCol from ClobTestTable where sno = 1");
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
assertTrue("No results retrieved", rs.next());
+ int secondKey = requestKey();
Clob insertClob = rs.getClob(1);
- psChar.setInt(1, 2);
- psChar.setClob(2, insertClob);
- psChar.execute();
+ psInsertClob.setInt(1, secondKey);
+ psInsertClob.setClob(2, insertClob);
+ psInsertClob.execute();
// Read back test data from database.
- rs = s.executeQuery(
- "select clobCol from ClobTestTable where sno = 2");
+ psFetchClob.setInt(1, secondKey);
+ rs = psFetchClob.executeQuery();
assertTrue("No results retrieved", rs.next());
Clob clobRetrieved = rs.getClob(1);
@@ -403,30 +488,31 @@
InputStream is = new java.io.ByteArrayInputStream(BYTES);
is.reset();
- PreparedStatement ps_sb = prepareStatement("insert into BlobTestTable values(?,?)");
-
//initially insert the data
- ps_sb.setInt(1,1);
- ps_sb.setBlob(2,is,BYTES.length);
- ps_sb.executeUpdate();
+ psInsertBlob.setInt(1, key);
+ psInsertBlob.setBlob(2, is, BYTES.length);
+ psInsertBlob.executeUpdate();
//Now query to retrieve the Blob
- ResultSet rs = s.executeQuery("select * from BlobTestTable where sno = 1");
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
rs.next();
- Blob blobToBeInserted = rs.getBlob(2);
+ Blob blobToBeInserted = rs.getBlob(1);
rs.close();
//Now use the setBlob method
- ps_sb.setInt(1,2);
- ps_sb.setBlob(2,blobToBeInserted);
- ps_sb.execute();
+ int secondKey = requestKey();
+ psInsertBlob.setInt(1, secondKey);
+ psInsertBlob.setBlob(2, blobToBeInserted);
+ psInsertBlob.execute();
- ps_sb.close();
+ psInsertBlob.close();
//Now test to see that the Blob has been stored correctly
- rs = s.executeQuery("select * from BlobTestTable where sno = 2");
+ psFetchBlob.setInt(1, secondKey);
+ rs = psFetchBlob.executeQuery();
rs.next();
- Blob blobRetrieved = rs.getBlob(2);
+ Blob blobRetrieved = rs.getBlob(1);
assertEquals(blobToBeInserted, blobRetrieved);
}
@@ -444,25 +530,24 @@
throws IOException, SQLException {
// Insert test data.
InputStream is = new ByteArrayInputStream(BYTES);
- PreparedStatement psByte = prepareStatement(
- "insert into BlobTestTable values (?,?)");
- psByte.setInt(1, 1);
- psByte.setBinaryStream(2, is);
- psByte.execute();
+ psInsertBlob.setInt(1, key);
+ psInsertBlob.setBinaryStream(2, is);
+ psInsertBlob.execute();
is.close();
// Must fetch Blob from database because we don't support
// Connection.createBlob on the client yet.
- ResultSet rs = s.executeQuery(
- "select blobCol from BlobTestTable where sno = 1");
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
assertTrue("No results retrieved", rs.next());
Blob insertBlob = rs.getBlob(1);
- psByte.setInt(1, 2);
- psByte.setBlob(2, insertBlob);
- psByte.execute();
+ int secondKey = requestKey();
+ psInsertBlob.setInt(1, secondKey);
+ psInsertBlob.setBlob(2, insertBlob);
+ psInsertBlob.execute();
// Read back test data from database.
- rs = s.executeQuery(
- "select blobCol from BlobTestTable where sno = 2");
+ psFetchBlob.setInt(1, secondKey);
+ rs = psFetchBlob.executeQuery();
assertTrue("No results retrieved", rs.next());
Blob blobRetrieved = rs.getBlob(1);
@@ -547,23 +632,22 @@
is.reset();
- PreparedStatement ps_sc = prepareStatement("insert into ClobTestTable values(?,?)");
-
//initially insert the data
- ps_sc.setInt(1,1);
- ps_sc.setCharacterStream(2,is,str.length());
- ps_sc.executeUpdate();
+ psInsertClob.setInt(1, key);
+ psInsertClob.setCharacterStream(2, is, str.length());
+ psInsertClob.executeUpdate();
//Now query to retrieve the Clob
- ResultSet rs = s.executeQuery("select * from ClobTestTable where sno = 1");
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
rs.next();
- Clob clobRetrieved = rs.getClob(2);
+ Clob clobRetrieved = rs.getClob(1);
rs.close();
String str_out = clobRetrieved.getSubString(1L,(int)clobRetrieved.length());
assertEquals("Error in inserting data into the Clob object",str,str_out);
- ps_sc.close();
+ psInsertClob.close();
}
public void testSetCharacterStreamLengthless()
@@ -571,16 +655,14 @@
// Insert test data.
String testString = "Test string for setCharacterStream\u1A00";
Reader reader = new StringReader(testString);
- PreparedStatement psChar = prepareStatement(
- "insert into ClobTestTable values (?,?)");
- psChar.setInt(1, 1);
- psChar.setCharacterStream(2, reader);
- psChar.execute();
+ psInsertClob.setInt(1, key);
+ psInsertClob.setCharacterStream(2, reader);
+ psInsertClob.execute();
reader.close();
// Read back test data from database.
- ResultSet rs = s.executeQuery(
- "select clobCol from ClobTestTable where sno = 1");
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
assertTrue("No results retrieved", rs.next());
Clob clobRetrieved = rs.getClob(1);
@@ -606,17 +688,16 @@
is.reset();
- PreparedStatement ps_sb = prepareStatement("insert into ClobTestTable values(?,?)");
-
//initially insert the data
- ps_sb.setInt(1,1);
- ps_sb.setAsciiStream(2,is,BYTES.length);
- ps_sb.executeUpdate();
+ psInsertClob.setInt(1, key);
+ psInsertClob.setAsciiStream(2, is, BYTES.length);
+ psInsertClob.executeUpdate();
//Now query to retrieve the Clob
- ResultSet rs = s.executeQuery("select * from ClobTestTable where sno = 1");
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
rs.next();
- Clob ClobRetrieved = rs.getClob(2);
+ Clob ClobRetrieved = rs.getClob(1);
rs.close();
try {
@@ -628,23 +709,21 @@
for(int i=0;i<BYTES.length;i++) {
assertEquals("Error in inserting data into the Clob",BYTES[i],bytes1[i]);
}
- ps_sb.close();
+ psInsertClob.close();
}
public void testSetAsciiStreamLengthless()
throws IOException, SQLException {
// Insert test data.
InputStream is = new ByteArrayInputStream(BYTES);
- PreparedStatement psAscii = prepareStatement(
- "insert into ClobTestTable values (?,?)");
- psAscii.setInt(1, 1);
- psAscii.setAsciiStream(2, is);
- psAscii.execute();
+ psInsertClob.setInt(1, key);
+ psInsertClob.setAsciiStream(2, is);
+ psInsertClob.execute();
is.close();
// Read back test data from database.
- ResultSet rs = s.executeQuery(
- "select clobCol from ClobTestTable where sno = 1");
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
assertTrue("No results retrieved", rs.next());
Clob clobRetrieved = rs.getClob(1);
@@ -660,7 +739,7 @@
// Cleanup
isRetrieved.close();
- psAscii.close();
+ psInsertClob.close();
}
/**
@@ -680,17 +759,16 @@
is.reset();
- PreparedStatement ps_sb = prepareStatement("insert into BlobTestTable values(?,?)");
-
//initially insert the data
- ps_sb.setInt(1,1);
- ps_sb.setBinaryStream(2,is,BYTES.length);
- ps_sb.executeUpdate();
+ psInsertBlob.setInt(1, key);
+ psInsertBlob.setBinaryStream(2, is, BYTES.length);
+ psInsertBlob.executeUpdate();
//Now query to retrieve the Clob
- ResultSet rs = s.executeQuery("select * from BlobTestTable where sno = 1");
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
rs.next();
- Blob blobRetrieved = rs.getBlob(2);
+ Blob blobRetrieved = rs.getBlob(1);
rs.close();
try {
@@ -703,23 +781,21 @@
for(int i=0;i<BYTES.length;i++) {
assertEquals("Error in inserting data into the Blob",BYTES[i],bytes1[i]);
}
- ps_sb.close();
+ psInsertBlob.close();
}
public void testSetBinaryStreamLengthless()
throws IOException, SQLException {
// Insert test data.
InputStream is = new ByteArrayInputStream(BYTES);
- PreparedStatement psBinary = prepareStatement(
- "insert into BlobTestTable values (?,?)");
- psBinary.setInt(1, 1);
- psBinary.setBinaryStream(2, is);
- psBinary.execute();
+ psInsertBlob.setInt(1, key);
+ psInsertBlob.setBinaryStream(2, is);
+ psInsertBlob.execute();
is.close();
// Read back test data from database.
- ResultSet rs = s.executeQuery(
- "select blobCol from BlobTestTable where sno = 1");
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
assertTrue("No results retrieved", rs.next());
Blob blobRetrieved = rs.getBlob(1);
@@ -735,6 +811,363 @@
// Cleanup
isRetrieved.close();
- psBinary.close();
+ psInsertBlob.close();
+ }
+
+ public void testSetBinaryStreamLengthLess1KOnBlob()
+ throws IOException, SQLException {
+ int length = 1*1024;
+ setBinaryStreamOnBlob(key, length, -1, 0, true);
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
+ assertTrue("Empty resultset", rs.next());
+ assertEquals(new LoopingAlphabetStream(length),
+ rs.getBinaryStream(1));
+ assertFalse("Resultset should have been exhausted", rs.next());
+ rs.close();
+ }
+
+ public void testSetBinaryStreamLengthLess32KOnBlob()
+ throws IOException, SQLException {
+ int length = 32*1024;
+ setBinaryStreamOnBlob(key, length, -1, 0, true);
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
+ assertTrue("Empty resultset", rs.next());
+ assertEquals(new LoopingAlphabetStream(length),
+ rs.getBinaryStream(1));
+ assertFalse("Resultset should have been exhausted", rs.next());
+ rs.close();
+ }
+
+ public void testSetBinaryStreamLengthLess65KOnBlob()
+ throws IOException, SQLException {
+ int length = 65*1024;
+ setBinaryStreamOnBlob(key, length, -1, 0, true);
+ psFetchBlob.setInt(1, key);
+ ResultSet rs = psFetchBlob.executeQuery();
+ assertTrue("Empty resultset", rs.next());
+ LoopingAlphabetStream s1 = new LoopingAlphabetStream(length);
+ assertEquals(new LoopingAlphabetStream(length),
+ rs.getBinaryStream(1));
+ assertFalse("Resultset should have been exhausted", rs.next());
+ rs.close();
+ }
+
+ public void testSetBinaryStreamLengthLessOnBlobTooLong() {
+ int length = 1*1024*1024+512;
+ try {
+ setBinaryStreamOnBlob(key, length, -1, 0, true);
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertSQLState("XCL30", sqle);
+ } else {
+ assertSQLState("22001", sqle);
+ }
+ }
+ }
+
+ public void testExceptionPathOnePage_bs()
+ throws SQLException {
+ int length = 11;
+ try {
+ setBinaryStreamOnBlob(key, length -1, length, 0, false);
+ fail("Inserted a BLOB with fewer bytes than specified");
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertSQLState("XSDA4", sqle);
+ } else {
+ assertSQLState("XN017", sqle);
+ }
+ }
+ }
+
+ public void testExceptionPathMultiplePages_bs()
+ throws SQLException {
+ int length = 1*1024*1024;
+ try {
+ setBinaryStreamOnBlob(key, length -1, length, 0, false);
+ fail("Inserted a BLOB with fewer bytes than specified");
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertSQLState("XSDA4", sqle);
+ } else {
+ assertSQLState("XN017", sqle);
+ }
+ }
+ }
+
+ public void testBlobExceptionDoesNotRollbackOtherStatements()
+ throws IOException, SQLException {
+ getConnection().setAutoCommit(false);
+ int[] keys = {key, requestKey(), requestKey()};
+ for (int i=0; i < keys.length; i++) {
+ psInsertBlob.setInt(1, keys[i]);
+ psInsertBlob.setNull(2, Types.BLOB);
+ assertEquals(1, psInsertBlob.executeUpdate());
+ }
+ // Now insert a BLOB that fails because the stream is too short.
+ int failedKey = requestKey();
+ int length = 1*1024*1024;
+ try {
+ setBinaryStreamOnBlob(failedKey, length -1, length, 0, false);
+ fail("Inserted a BLOB with less data than specified");
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertSQLState("XSDA4", sqle);
+ } else {
+ assertSQLState("XN017", sqle);
+ }
+ }
+ // Now make sure the previous statements are there, and that the last
+ // BLOB is not.
+ ResultSet rs;
+ for (int i=0; i < keys.length; i++) {
+ psFetchBlob.setInt(1, keys[i]);
+ rs = psFetchBlob.executeQuery();
+ assertTrue(rs.next());
+ assertFalse(rs.next());
+ rs.close();
+ }
+ psFetchBlob.setInt(1, failedKey);
+ rs = psFetchBlob.executeQuery();
+ // When using the Derby client driver, the data seems to be padded
+ // with 0s and inserted... Thus, the select returns a row.
+ if (!usingEmbedded()) {
+ assertTrue(rs.next());
+ InputStream is = rs.getBinaryStream(1);
+ int lastByte = -1;
+ int b = 99; // Just a value > 0.
+ while (b > -1) {
+ lastByte = b;
+ b = is.read();
+ }
+ assertEquals("Last padded byte is not 0", 0, lastByte);
+ }
+ assertFalse(rs.next());
+ rs.close();
+ rollback();
+ // Make sure all data is gone after the rollback.
+ for (int i=0; i < keys.length; i++) {
+ psFetchBlob.setInt(1, keys[i]);
+ rs = psFetchBlob.executeQuery();
+ assertFalse(rs.next());
+ rs.close();
+ }
+ // Make sure the failed insert has not "reappeared" somehow...
+ psFetchBlob.setInt(1, failedKey);
+ rs = psFetchBlob.executeQuery();
+ assertFalse(rs.next());
+
+ }
+
+ public void testSetAsciiStreamLengthLess1KOnClob()
+ throws IOException, SQLException {
+ int length = 1*1024;
+ setAsciiStream(psInsertClob, key, length, -1, 0, true);
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
+ assertTrue("Empty resultset", rs.next());
+ assertEquals(new LoopingAlphabetStream(length),
+ rs.getAsciiStream(1));
+ assertFalse("Resultset should have been exhausted", rs.next());
+ rs.close();
+ }
+
+ public void testSetAsciiStreamLengthLess32KOnClob()
+ throws IOException, SQLException {
+ int length = 32*1024;
+ setAsciiStream(psInsertClob, key, length, -1, 0, true);
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
+ assertTrue("Empty resultset", rs.next());
+ assertEquals(new LoopingAlphabetStream(length),
+ rs.getAsciiStream(1));
+ assertFalse("Resultset should have been exhausted", rs.next());
+ rs.close();
+ }
+
+ public void testSetAsciiStreamLengthLess65KOnClob()
+ throws IOException, SQLException {
+ int length = 65*1024;
+ setAsciiStream(psInsertClob, key, length, -1, 0, true);
+ psFetchClob.setInt(1, key);
+ ResultSet rs = psFetchClob.executeQuery();
+ assertTrue("Empty resultset", rs.next());
+ assertEquals(new LoopingAlphabetStream(length),
+ rs.getAsciiStream(1));
+ assertFalse("Resultset should have been exhausted", rs.next());
+ rs.close();
+ }
+
+ public void testSetAsciiStreamLengthLessOnClobTooLong() {
+ int length = 1*1024*1024+512;
+ try {
+ setAsciiStream(psInsertClob, key, length, -1, 0, true);
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertSQLState("XSDA4", sqle);
+ } else {
+ assertSQLState("22001", sqle);
+ }
+ }
+ }
+
+ public void testSetAsciiStreamLengthLessOnClobTooLongTruncate()
+ throws SQLException {
+ int trailingBlanks = 512;
+ int length = 1*1024*1024 + trailingBlanks;
+ setAsciiStream(psInsertClob, key, length, -1, trailingBlanks, true);
+ }
+
+ public void testSetAsciiStreamLengthlessOnLongVarCharTooLong() {
+ int length = 32700+512;
+ try {
+ setAsciiStream(psInsertLongVarchar, key, length, -1, 0, true);
+ fail("Inserted a LONG VARCHAR that is too long");
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertInternalDerbyIOExceptionState("XCL30", "22001", sqle);
+ } else {
+ assertSQLState("22001", sqle);
+ }
+ }
+ }
+
+ public void testSetAsciiStreamLengthlessOnLongVarCharDontTruncate() {
+ int trailingBlanks = 2000;
+ int length = 32000 + trailingBlanks;
+ try {
+ setAsciiStream(psInsertLongVarchar, key, length, -1,
+ trailingBlanks, true);
+ fail("Truncation is not allowed for LONG VARCHAR");
+ } catch (SQLException sqle) {
+ if (usingEmbedded()) {
+ assertInternalDerbyIOExceptionState("XCL30", "22001", sqle);
+ } else {
+ assertSQLState("22001", sqle);
+ }
+ }
+ }
+
+ /************************************************************************
+ * A U X I L I A R Y M E T H O D S *
+ ************************************************************************/
+
+ /**
+ * Insert data into a Blob column with setBinaryStream.
+ *
+ * @param id unique id for inserted row
+ * @param actualLength the actual length of the stream
+ * @param specifiedLength the specified length of the stream
+ * @param trailingBlanks number of characters at the end that is blank
+ * @param lengthLess whether to use the length less overloads or not
+ */
+ private void setBinaryStreamOnBlob(int id,
+ int actualLength,
+ int specifiedLength,
+ int trailingBlanks,
+ boolean lengthLess)
+ throws SQLException {
+ psInsertBlob.setInt(1, id);
+ if (lengthLess) {
+ psInsertBlob.setBinaryStream(2, new LoopingAlphabetStream(
+ actualLength,
+ trailingBlanks));
+ } else {
+ psInsertBlob.setBinaryStream(2,
+ new LoopingAlphabetStream(
+ actualLength,
+ trailingBlanks),
+ specifiedLength);
+ }
+ assertEquals("Insert with setBinaryStream failed",
+ 1, psInsertBlob.executeUpdate());
+ }
+
+ /**
+ * Insert data into a column with setAsciiStream.
+ * The prepared statement passed must have two positional parameters;
+ * one int and one more. Depending on the last parameter, the execute
+ * might succeed or it might fail. This is intended behavior, and should
+ * be handled by the caller. For instance, calling this method on an
+ * INT-column would fail, calling it on a CLOB-column would succeed.
+ *
+ * @param id unique id for inserted row
+ * @param actualLength the actual length of the stream
+ * @param specifiedLength the specified length of the stream
+ * @param trailingBlanks number of characters at the end that is blank
+ * @param lengthLess whether to use the length less overloads or not
+ */
+ private void setAsciiStream(PreparedStatement ps,
+ int id,
+ int actualLength,
+ int specifiedLength,
+ int trailingBlanks,
+ boolean lengthLess)
+ throws SQLException {
+ ps.setInt(1, id);
+ if (lengthLess) {
+ ps.setAsciiStream(2,
+ new LoopingAlphabetStream(
+ actualLength,
+ trailingBlanks));
+ } else {
+ ps.setAsciiStream(2,
+ new LoopingAlphabetStream(
+ actualLength,
+ trailingBlanks),
+ specifiedLength);
+ }
+ assertEquals("Insert with setAsciiStream failed",
+ 1, ps.executeUpdate());
+ }
+
+ /**
+ * Get next key to id inserted data with.
+ */
+ private static int requestKey() {
+ return globalKey++;
+ }
+
+ /**
+ * Return the last chained SQLException.
+ * If there are no exceptions chained, the original one is returned.
+ */
+ private SQLException getLastSQLException(SQLException sqle) {
+ SQLException last = sqle;
+ SQLException next = sqle;
+ while (next != null) {
+ last = next;
+ next = last.getNextException();
+ }
+ return last;
+ }
+
+ /**
+ * This methods is not to be used, but sometimes you have to!
+ *
+ * @param preSQLState the expected outer SQL state
+ * @param expectedInternal the expected internal SQL state
+ * @param sqle the outer SQLException
+ */
+ private void assertInternalDerbyIOExceptionState(
+ String preSQLState,
+ String expectedInternal,
+ SQLException sqle) {
+ assertSQLState("Outer/public SQL state incorrect",
+ preSQLState, sqle);
+ // We need to dig a little with the current way exceptions are
+ // being reported. We can use getCause because we always run with
+ // Mustang/Java SE 6.
+ Throwable cause = getLastSQLException(sqle).getCause();
+ assertTrue("Exception not an EmbedSQLException",
+ cause instanceof EmbedSQLException);
+ cause = ((EmbedSQLException)cause).getJavaException();
+ assertTrue("Exception not a DerbyIOException",
+ cause instanceof DerbyIOException);
+ DerbyIOException dioe = (DerbyIOException)cause;
+ assertEquals("Incorrect internal SQL state", expectedInternal,
+ dioe.getSQLState());
}
}
Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/build.xml
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/build.xml?rev=437146&r1=437145&r2=437146&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/build.xml (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/util/build.xml Sat Aug 26 04:39:20 2006
@@ -62,6 +62,7 @@
</classpath>
<include name="${this.dir}/*.java"/>
<include name="${this.dir}/StaticInitializers/*.java"/>
+ <include name="${this.dir}/streams/*.java"/>
<include name="${this.dir}/corruptio/*.java"/>
<exclude name="${this.dir}/XATestUtil.java"/>
</javac>