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 kr...@apache.org on 2007/04/18 18:17:05 UTC
svn commit: r530085 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/jdbc/
testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Author: kristwaa
Date: Wed Apr 18 09:17:01 2007
New Revision: 530085
URL: http://svn.apache.org/viewvc?view=rev&rev=530085
Log:
DERBY-2346: Provide set methods for clob for embedded driver.
Patch contributed by Anurag Shekar.
Added:
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobAsciiStream.java (with props)
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java (with props)
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUpdateableReader.java (with props)
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUtf8Writer.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobUpdateableReaderTest.java (with props)
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBInputStream.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LobStreamsTest.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java
Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobAsciiStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobAsciiStream.java?view=auto&rev=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobAsciiStream.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobAsciiStream.java Wed Apr 18 09:17:01 2007
@@ -0,0 +1,87 @@
+/*
+ Derby - Class org.apache.derby.impl.jdbc.ClobAsciiStream
+
+ Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+
+ Licensed 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.impl.jdbc;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+final class ClobAsciiStream extends OutputStream {
+ private Writer writer;
+
+ ClobAsciiStream (Writer writer){
+ this.writer = writer;
+ }
+
+ /**
+ * Writes the specified byte to this output stream. The general
+ * contract for <code>write</code> is that one byte is written
+ * to the output stream. The byte to be written is the eight
+ * low-order bits of the argument <code>b</code>. The 24
+ * high-order bits of <code>b</code> are ignored.
+ * <p>
+ * Subclasses of <code>OutputStream</code> must provide an
+ * implementation for this method.
+ *
+ * @param b the <code>byte</code>.
+ * @exception IOException if an I/O error occurs. In particular,
+ * an <code>IOException</code> may be thrown if the
+ * output stream has been closed.
+ */
+ public void write(int b) throws IOException {
+ writer.write (b);
+ }
+
+ /**
+ * Writes <code>len</code> bytes from the specified byte array
+ * starting at offset <code>off</code> to this output stream.
+ * The general contract for <code>write(b, off, len)</code> is that
+ * some of the bytes in the array <code>b</code> are written to the
+ * output stream in order; element <code>b[off]</code> is the first
+ * byte written and <code>b[off+len-1]</code> is the last byte written
+ * by this operation.
+ * <p>
+ * The <code>write</code> method of <code>OutputStream</code> calls
+ * the write method of one argument on each of the bytes to be
+ * written out. Subclasses are encouraged to override this method and
+ * provide a more efficient implementation.
+ * <p>
+ * If <code>b</code> is <code>null</code>, a
+ * <code>NullPointerException</code> is thrown.
+ * <p>
+ * If <code>off</code> is negative, or <code>len</code> is negative, or
+ * <code>off+len</code> is greater than the length of the array
+ * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs. In particular,
+ * an <code>IOException</code> is thrown if the output
+ * stream is closed.
+ */
+ public void write(byte[] b, int off, int len) throws IOException {
+ char [] c = new char [len];
+ for (int i = off; i < len; i++) {
+ c [i - off] = (char) b [i];
+ }
+ writer.write(c);
+ }
+}
Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobAsciiStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java?view=auto&rev=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java Wed Apr 18 09:17:01 2007
@@ -0,0 +1,219 @@
+/*
+ Derby - Class org.apache.derby.impl.jdbc.ClobStreamControl
+
+ Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+
+ Licensed 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.impl.jdbc;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UTFDataFormatException;
+import java.io.Writer;
+import java.sql.SQLException;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.util.ByteArray;
+
+final class ClobStreamControl extends LOBStreamControl {
+
+ private ConnectionChild conChild;
+ /**
+ * Constructs ClobStreamControl
+ * @param dbName
+ * @param conChild
+ */
+ ClobStreamControl (String dbName, ConnectionChild conChild) {
+ super (dbName);
+ this.conChild = conChild;
+ }
+
+ /**
+ * Finds the positon in bytes for a utf8 char postion starting
+ * from startPos (bytes).
+ * @param startPos in bytes
+ * @param charPos in chars
+ * @return stream position for the given char position
+ * @throws IOException
+ */
+ synchronized long getStreamPosition (long startPos, long charPos) throws IOException {
+ InputStream in = new BufferedInputStream (getInputStream (startPos));
+ long charLength = 0;
+ long streamLength = 0;
+ //utf decoding routine
+ while (charLength < charPos) {
+ int c = in.read();
+ if (c < 0)
+ return -1;
+ charLength ++;
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ //found char of one byte width
+ streamLength++;
+ }
+ else if (c > 0x07FF) {
+ //found char of three byte width
+ if (in.skip (2) < 2) {
+ //no second and third byte present
+ throw new UTFDataFormatException();
+ }
+ streamLength += 3;
+ break;
+ }
+ else {
+ //found char of three byte width
+ if (in.skip (1) != 1) {
+ //no second and third byte present
+ throw new UTFDataFormatException();
+ }
+ streamLength += 2;
+ }
+ }
+
+ in.close();
+ return streamLength;
+ }
+
+ /**
+ * constructs and returns a writer.
+ * @param pos
+ * @return Writer
+ * @throws IOException, SQLException
+ */
+ synchronized Writer getWriter (long pos) throws IOException, SQLException {
+ long charPos = getStreamPosition (0, pos);
+ if (charPos == -1)
+ throw Util.generateCsSQLException (SQLState.BLOB_POSITION_TOO_LARGE,
+ "" + (pos + 1));
+ return new ClobUtf8Writer (this, getStreamPosition (0, charPos));
+ }
+
+ /**
+ * constructs and reurns a reader.
+ * @param pos
+ * @return
+ * @throws IOException, SQLException
+ */
+ Reader getReader (long pos) throws IOException, SQLException {
+ Reader isr = new ClobUpdateableReader (
+ (LOBInputStream) getInputStream (0), conChild);
+
+ long leftToSkip = pos;
+ while (leftToSkip > 0) {
+ leftToSkip -= isr.skip (leftToSkip);
+ }
+ return isr;
+ }
+
+ /**
+ * returns a substring.
+ * @param bIndex
+ * @param eIndex
+ * @return
+ * @throws IOException, SQLException
+ */
+ synchronized String getSubstring (long bIndex, long eIndex)
+ throws IOException, SQLException {
+ Reader r = getReader(bIndex);
+ char [] buff = new char [(int) (eIndex - bIndex)];
+ int length = 0;
+ do {
+ int ret = r.read (buff, length, (int) (eIndex - bIndex) - length);
+ if (ret == -1 )
+ break;
+ length += ret;
+ } while (length < eIndex - bIndex);
+ return new String (buff, 0, length);
+ }
+
+ /**
+ * returns number of charecter in the clob.
+ * @return char length
+ * @throws IOException, SQLException
+ */
+ synchronized long getCharLength () throws IOException, SQLException {
+ Reader reader = getReader(0);
+ char [] dummy = new char [4 * 1024];
+ int length = 0;
+ do {
+ long ret = reader.read (dummy);
+ if (ret == -1) break;
+ length += ret;
+ }while (true);
+ return length;
+ }
+
+ /**
+ * returns the size of clob in bytes.
+ * @return
+ * @throws IOException
+ */
+ long getByteLength () throws IOException {
+ return super.getLength();
+ }
+
+ /**
+ * inserts a string at a given postion.
+ * @param str
+ * @param pos byte postion
+ * @return current byte postion
+ * @throws IOException
+ */
+ synchronized long insertString (String str, long pos)
+ throws IOException, SQLException {
+ int len = str.length();
+ if (pos == super.getLength()) {
+ byte b [] = getByteFromString (str);
+ long l = write (b, 0, b.length, pos);
+ return str.length();
+ }
+ long endPos = getStreamPosition (pos, len);
+ endPos = (endPos < 0) ? getLength() : pos + endPos;
+ replaceBytes (getByteFromString (str), pos, endPos);
+ return str.length();
+ }
+
+ /**
+ * Converts a string into utf8 byte array.
+ * @param str
+ * @return utf8 bytes array
+ */
+ private byte[] getByteFromString (String str) {
+ //create a buffer with max size possible
+ byte [] buffer = new byte [3 * str.length()];
+ int len = 0;
+ //start decoding
+ for (int i = 0; i < str.length(); i++) {
+ int c = str.charAt (i);
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ buffer[len++] = (byte) c;
+ }
+ else if (c > 0x07FF) {
+ buffer[len++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
+ buffer[len++] = (byte) (0x80 | ((c >> 6) & 0x3F));
+ buffer[len++] = (byte) (0x80 | ((c >> 0) & 0x3F));
+ }
+ else {
+ buffer[len++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
+ buffer[len++] = (byte) (0x80 | ((c >> 0) & 0x3F));
+ }
+ }
+ byte [] buff = new byte [len];
+ System.arraycopy (buffer, 0, buff, 0, len);
+ return buff;
+ }
+}
Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUpdateableReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUpdateableReader.java?view=auto&rev=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUpdateableReader.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUpdateableReader.java Wed Apr 18 09:17:01 2007
@@ -0,0 +1,96 @@
+/*
+ *
+ * Derby - Class ClobUpdateableReader
+ *
+ * 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.impl.jdbc;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * ClobUpdateableReader is used to create Reader over InputStream. This class is
+ * aware that underlying stream can be modified and reinitializes itsef if it
+ * detects any change in stream hence invalidating the cache so the changes are
+ * reflected immidiatly.
+ */
+
+final class ClobUpdateableReader extends Reader {
+
+ private Reader streamReader;
+ private long pos;
+ private LOBInputStream stream;
+ private ConnectionChild conChild;
+
+ /**
+ * Constructs a Reader over a LOBInputStream.
+ * @param stream
+ * @throws IOException
+ */
+ ClobUpdateableReader (LOBInputStream stream, ConnectionChild conChild)
+ throws IOException {
+ this.conChild = conChild;
+ this.stream = stream;
+ init (0);
+ }
+
+ /**
+ * Reads chars into the cbuf char array. Changes made in uderlying storage
+ * will be reflected immidiatly from the corrent position.
+ * @param cbuf buffer to read into
+ * @param off offet of the cbuf array to start writing read chars
+ * @param len number of chars to be read
+ * @return number of bytes read
+ * @throws IOException
+ */
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ if (stream.isObsolete()) {
+ stream.reInitialize();
+ init (pos);
+ }
+ int ret = streamReader.read (cbuf, off, len);
+ if (ret >= 0) {
+ pos += ret;
+ }
+ return ret;
+ }
+
+ /**
+ * Closes the reader.
+ * @throws IOException
+ */
+ public void close() throws IOException {
+ streamReader.close();
+ }
+
+ /**
+ * Initializes the streamReader and skips to the given position.
+ * @param skip
+ * @throws IOException
+ */
+ private void init(long skip) throws IOException {
+ streamReader = new UTF8Reader (stream, 0, stream.length (),
+ conChild,
+ conChild.getConnectionSynchronization());
+ long remainToSkip = skip;
+ while (remainToSkip > 0) {
+ long skipBy = streamReader.skip(remainToSkip);
+ remainToSkip -= skipBy;
+ }
+ pos = skip;
+ }
+}
Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUpdateableReader.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUtf8Writer.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUtf8Writer.java?view=auto&rev=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUtf8Writer.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUtf8Writer.java Wed Apr 18 09:17:01 2007
@@ -0,0 +1,111 @@
+/*
+ Derby - Class org.apache.derby.impl.jdbc.ClobUtf8Writer
+
+ Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+
+ Licensed 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.impl.jdbc;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.sql.SQLException;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.services.i18n.MessageService;
+
+/**
+ * Writer implementation for Clob.
+ */
+final class ClobUtf8Writer extends Writer {
+ private ClobStreamControl control;
+ private long pos; //postion in bytes
+ private boolean closed;
+
+ /**
+ * Constructor.
+ * @param control
+ * @param pos
+ * @return
+ */
+ ClobUtf8Writer(ClobStreamControl control, long pos) {
+ this.control = control;
+ this.pos = pos;
+ closed = false;
+ }
+
+ /**
+ * Flushes the stream. If the stream has saved any characters from the
+ * various write() methods in a buffer, write them immediately to their
+ * intended destination. Then, if that destination is another character or
+ * byte stream, flush it. Thus one flush() invocation will flush all the
+ * buffers in a chain of Writers and OutputStreams.
+ *
+ * <p> If the intended destination of this stream is an abstraction provided
+ * by the underlying operating system, for example a file, then flushing the
+ * stream guarantees only that bytes previously written to the stream are
+ * passed to the operating system for writing; it does not guarantee that
+ * they are actually written to a physical device such as a disk drive.
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ public void flush() throws IOException {
+ if (closed)
+ throw new IOException (
+ MessageService.getTextMessage (SQLState.LANG_STREAM_CLOSED));
+ //no op
+ }
+
+ /**
+ * Closes the stream, flushing it first. Once the stream has been closed,
+ * further write() or flush() invocations will cause an IOException to be
+ * thrown. Closing a previously closed stream has no effect.
+ */
+ public void close() {
+ closed = true;
+ }
+
+ /**
+ * Writes a portion of an array of characters.
+ *
+ * @param cbuf
+ * Array of characters
+ * @param off
+ * Offset from which to start writing characters
+ * @param len
+ * Number of characters to write
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ if (closed)
+ throw new IOException (
+ MessageService.getTextMessage (SQLState.LANG_STREAM_CLOSED));
+ try {
+ long ret = control.insertString (String.copyValueOf (
+ cbuf, off, len),
+ pos);
+ if (ret > 0)
+ pos += ret;
+ }
+ catch (SQLException e) {
+ IOException ioe = new IOException (e.getMessage());
+ ioe.initCause (e);
+ throw ioe;
+ }
+ }
+}
Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobUtf8Writer.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java Wed Apr 18 09:17:01 2007
@@ -72,9 +72,9 @@
final class EmbedClob extends ConnectionChild implements Clob
{
// clob is either a string or stream
- private boolean isString;
+ private boolean materialized;
private InputStream myStream;
- private String myString;
+ private ClobStreamControl control;
//This boolean variable indicates whether the Clob object has
//been invalidated by calling free() on it
@@ -88,18 +88,29 @@
* Clob.
*
* @param con The Connection object associated with this EmbedClob object.
+ * @throws SQLException
*
*/
- EmbedClob(String clobString,EmbedConnection con) {
+ EmbedClob(String clobString,EmbedConnection con) throws SQLException {
super(con);
- myString = clobString;
- isString = true;
+ materialized = true;
+ control = new ClobStreamControl (con.getDBName(), this);
+ try {
+ control.insertString (clobString, 0);
+ }
+
+ catch (IOException e) {
+ throw Util.setStreamFailure (e);
+ }
}
- /*
- This constructor should only be called by EmbedResultSet.getClob
- */
+ /**
+ * This constructor should only be called by EmbedResultSet.getClob
+ * @param dvd
+ * @param con
+ * @throws StandardException
+ */
protected EmbedClob(DataValueDescriptor dvd, EmbedConnection con)
throws StandardException
{
@@ -112,10 +123,19 @@
myStream = dvd.getStream();
if (myStream == null)
{
- isString = true;
- myString = dvd.getString();
- if (SanityManager.DEBUG)
- SanityManager.ASSERT(myString != null,"clob has a null value underneath");
+ control = new ClobStreamControl (con.getDBName(), this);
+ materialized = true;
+ try {
+ String str = dvd.getString();
+ control.insertString (dvd.getString(), 0);
+ }
+ catch (SQLException sqle) {
+ throw StandardException.newException (sqle.getSQLState(), sqle);
+ }
+ catch (IOException e) {
+ throw StandardException.newException (
+ SQLState.SET_STREAM_FAILURE, e);
+ }
}
else
{
@@ -162,8 +182,13 @@
//the Clob object has been freed by calling free() on it
checkValidity();
// if we have a string, not a stream
- if (isString)
- return myString.length();
+ try {
+ if (materialized)
+ return control.getCharLength ();
+ }
+ catch (IOException e) {
+ throw Util.setStreamFailure (e);
+ }
Object synchronization = getConnectionSynchronization();
@@ -240,15 +265,21 @@
SQLState.BLOB_NONPOSITIVE_LENGTH, new Integer(length));
// if we have a string, not a stream
- if (isString)
+ if (materialized)
{
- int sLength = myString.length();
- if (sLength + 1 < pos)
- throw Util.generateCsSQLException(
- SQLState.BLOB_POSITION_TOO_LARGE, new Long(pos));
- int endIndex = ((int) pos) + length - 1;
- // cannot go over length of string
- return myString.substring(((int) pos) - 1, (sLength > endIndex ? endIndex : sLength));
+ try {
+ long sLength = control.getCharLength ();
+ if (sLength + 1 < pos)
+ throw Util.generateCsSQLException(
+ SQLState.BLOB_POSITION_TOO_LARGE, new Long(pos));
+ int endIndex = ((int) pos) + length - 1;
+ // cannot go over length of string
+ return control.getSubstring (pos - 1,
+ (sLength > endIndex ? endIndex : sLength));
+ }
+ catch (IOException e) {
+ throw Util.setStreamFailure (e);
+ }
}
Object synchronization = getConnectionSynchronization();
@@ -305,20 +336,18 @@
//the Clob object has been freed by calling free() on it
checkValidity();
- // if we have a string, not a stream
- if (isString)
- {
- return new StringReader(myString);
- }
-
- Object synchronization = getConnectionSynchronization();
+ Object synchronization = getConnectionSynchronization();
synchronized (synchronization)
{
setupContextStack();
try {
- return getCharacterStreamAtPos(1, synchronization);
+ if (materialized) {
+ return control.getReader (0);
+ }
+
+ return getCharacterStreamAtPos(1, synchronization);
}
catch (Throwable t)
{
@@ -348,24 +377,30 @@
return new ReaderToAscii(getCharacterStream());
}
- private UTF8Reader getCharacterStreamAtPos(long position, Object synchronization)
- throws IOException, StandardException
- {
- ((Resetable)myStream).resetStream();
- UTF8Reader clobReader = new UTF8Reader(myStream, 0, this, synchronization);
-
- // skip to the correct position (pos is one based)
- long remainToSkip = position - 1;
- while (remainToSkip > 0) {
- long skipBy = clobReader.skip(remainToSkip);
- if (skipBy == -1)
- return null;
-
- remainToSkip -= skipBy;
- }
-
- return clobReader;
- }
+ private UTF8Reader getCharacterStreamAtPos(long position, Object synchronization)
+ throws IOException, StandardException {
+ UTF8Reader clobReader = null;
+ if (materialized)
+ clobReader = new UTF8Reader (control.getInputStream (0), 0,
+ control.getByteLength(),
+ this, control);
+ else {
+ ((Resetable)myStream).resetStream();
+ clobReader = new UTF8Reader(myStream, 0, this, synchronization);
+ }
+
+ // skip to the correct position (pos is one based)
+ long remainToSkip = position - 1;
+ while (remainToSkip > 0) {
+ long skipBy = clobReader.skip(remainToSkip);
+ if (skipBy == -1)
+ return null;
+
+ remainToSkip -= skipBy;
+ }
+
+ return clobReader;
+ }
/**
@@ -422,83 +457,75 @@
if (searchStr == "")
return start; // match DB2's SQL LOCATE function
- // if we have a string, not a stream
- if (isString)
+ Object synchronization = getConnectionSynchronization();
+ synchronized (synchronization)
{
- // avoid truncation errors in the cast of start to an int.
- if (start > myString.length())
- return -1;
-
- int result = myString.indexOf(searchStr, (int) start-1);
- return result < 0 ? -1 : result + 1;
- }
- else // we have a stream
- {
- Object synchronization = getConnectionSynchronization();
- synchronized (synchronization)
- {
- pushStack = !getEmbedConnection().isClosed();
- if (pushStack)
- setupContextStack();
- int matchCount = 0;
- long pos = start - 1;
- long newStart = -1;
- Reader reader = getCharacterStreamAtPos (start, this);
- char [] tmpClob = new char [256];
- boolean reset;
- for (;;) {
- reset = false;
- int readCount = reader.read (tmpClob);
- if (readCount == -1)
- return -1;
- if (readCount == 0)
- continue;
- for (int clobOffset = 0;
- clobOffset < readCount; clobOffset++) {
- if (tmpClob [clobOffset]
- == searchStr.charAt (matchCount)) {
- //find the new starting position in
- // case this match is unsuccessful
- if (matchCount != 0 && newStart == -1
- && tmpClob [clobOffset]
- == searchStr.charAt (0)) {
- newStart = pos + clobOffset + 1;
- }
- matchCount ++;
- if (matchCount == searchStr.length()) {
- //return after converting the position
- //to 1 based index
- return pos + clobOffset
- - searchStr.length() + 1 + 1;
- }
+ pushStack = !getEmbedConnection().isClosed();
+ if (pushStack)
+ setupContextStack();
+ int matchCount = 0;
+ long pos = start - 1;
+ long newStart = -1;
+ Reader reader = getCharacterStreamAtPos (start, this);
+ char [] tmpClob = new char [4096];
+ boolean reset;
+ for (;;) {
+ reset = false;
+ int readCount = reader.read (tmpClob);
+ if (readCount == -1)
+ return -1;
+ if (readCount == 0)
+ continue;
+ for (int clobOffset = 0;
+ clobOffset < readCount; clobOffset++) {
+ if (tmpClob [clobOffset]
+ == searchStr.charAt (matchCount)) {
+ //find the new starting position in
+ // case this match is unsuccessful
+ if (matchCount != 0 && newStart == -1
+ && tmpClob [clobOffset]
+ == searchStr.charAt (0)) {
+ newStart = pos + clobOffset + 1;
+ }
+ matchCount ++;
+ if (matchCount == searchStr.length()) {
+ //return after converting the position
+ //to 1 based index
+ return pos + clobOffset
+ - searchStr.length() + 1 + 1;
}
- else {
- if (matchCount > 0) {
- matchCount = 0;
- if (newStart == -1) {
- continue;
+ }
+ else {
+ if (matchCount > 0) {
+ if (newStart == -1) {
+ if (matchCount > 1) {
+ //compensate for increment in the "for"
+ clobOffset--;
}
- if (newStart < pos) {
- pos = newStart;
- reader.close();
- reader = getCharacterStreamAtPos
- (newStart + 1, this);
- newStart = -1;
- reset = true;
- break;
- }
- clobOffset = (int) (newStart - pos) - 1;
- newStart = -1;
+ matchCount = 0;
continue;
}
+ matchCount = 0;
+ if (newStart < pos) {
+ pos = newStart;
+ reader.close();
+ reader = getCharacterStreamAtPos
+ (newStart + 1, this);
+ newStart = -1;
+ reset = true;
+ break;
+ }
+ clobOffset = (int) (newStart - pos) - 1;
+ newStart = -1;
+ continue;
}
}
- if (!reset) {
- pos += readCount;
- }
}
-
+ if (!reset) {
+ pos += readCount;
+ }
}
+
}
}
catch (Throwable t)
@@ -546,7 +573,7 @@
synchronized (getConnectionSynchronization())
{
- char[] subPatternChar = new char[256];
+ char[] subPatternChar = new char[1024];
boolean seenOneCharacter = false;
@@ -629,7 +656,7 @@
protected void finalize()
{
// System.out.println("finalizer called");
- if (!isString)
+ if (!materialized)
((Resetable)myStream).closeStream();
}
@@ -659,13 +686,11 @@
* @return the number of characters written
* @exception SQLException Feature not implemented for now.
*/
- public int setString(long pos, String parameterName)
- throws SQLException
- {
- throw Util.notImplemented();
+ public int setString(long pos, String str) throws SQLException {
+ return setString (pos, str, 0, str.length());
}
- /**
+ /**
* JDBC 3.0
*
* Writes len characters of str, starting at character offset, to the CLOB value
@@ -678,11 +703,23 @@
* @return the number of characters written
* @exception SQLException Feature not implemented for now.
*/
- public int setString(long pos, String str, int offset, int len)
- throws SQLException
- {
- throw Util.notImplemented();
- }
+ public int setString(long pos, String str, int offset, int len)
+ throws SQLException {
+ try {
+ if (!materialized) {
+ control.copyData(myStream, length());
+ materialized = true;
+ }
+ long charPos = control.getStreamPosition(0, pos - 1);
+ if (charPos == -1)
+ throw Util.generateCsSQLException(
+ SQLState.BLOB_POSITION_TOO_LARGE, "" + pos);
+ return (int) control.insertString(str.substring (offset,
+ (offset + len)), charPos);
+ } catch (IOException e) {
+ throw Util.setStreamFailure(e);
+ }
+ }
/**
* JDBC 3.0
@@ -694,11 +731,13 @@
* @return the stream to which ASCII encoded characters can be written
* @exception SQLException Feature not implemented for now.
*/
- public java.io.OutputStream setAsciiStream(long pos)
- throws SQLException
- {
- throw Util.notImplemented();
- }
+ public java.io.OutputStream setAsciiStream(long pos) throws SQLException {
+ try {
+ return new ClobAsciiStream (control.getWriter(pos - 1));
+ } catch (IOException e) {
+ throw Util.setStreamFailure(e);
+ }
+ }
/**
* JDBC 3.0
@@ -710,11 +749,17 @@
* @return the stream to which Unicode encoded characters can be written
* @exception SQLException Feature not implemented for now.
*/
- public java.io.Writer setCharacterStream(long pos)
- throws SQLException
- {
- throw Util.notImplemented();
- }
+ public java.io.Writer setCharacterStream(long pos) throws SQLException {
+ try {
+ if (!materialized) {
+ control.copyData(myStream, length());
+ materialized = true;
+ }
+ return control.getWriter(pos - 1);
+ } catch (IOException e) {
+ throw Util.setStreamFailure(e);
+ }
+ }
/**
* JDBC 3.0
@@ -725,8 +770,7 @@
* value should be truncated
* @exception SQLException Feature not implemented for now.
*/
- public void truncate(long len)
- throws SQLException
+ public void truncate(long len) throws SQLException
{
throw Util.notImplemented();
}
@@ -754,10 +798,17 @@
//valid
isValid = false;
- if (!isString)
+ if (!materialized) {
((Resetable)myStream).closeStream();
- else
- myString = null;
+ }
+ else {
+ try {
+ control.free();
+ }
+ catch (IOException e) {
+ throw Util.setStreamFailure(e);
+ }
+ }
}
public java.io.Reader getCharacterStream(long pos, long length)
@@ -791,5 +842,6 @@
private void checkValidity() throws SQLException{
if(!isValid)
throw newSQLException(SQLState.LOB_OBJECT_INVALID);
+ localConn.checkIfClosed();
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBInputStream.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBInputStream.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBInputStream.java Wed Apr 18 09:17:01 2007
@@ -36,12 +36,13 @@
private boolean closed;
private LOBStreamControl control;
private long pos;
+ private long updateCount;
LOBInputStream(LOBStreamControl control, long position) {
closed = false;
this.control = control;
pos = position;
-
+ updateCount = control.getUpdateCount ();
}
/**
@@ -173,5 +174,29 @@
SQLState.BLOB_INVALID_OFFSET)))
throw new ArrayIndexOutOfBoundsException (e.getMessage());
throw new IOException(e.getMessage());
+ }
+
+ /**
+ * Checks if underlying StreamControl has been updated.
+ * @return if stream is modified since created
+ */
+ boolean isObsolete () {
+ return updateCount != control.getUpdateCount();
+ }
+
+ /**
+ * Reinitializes the stream and sets the current pointer to zero.
+ */
+ void reInitialize () {
+ updateCount = control.getUpdateCount();
+ pos = 0;
+ }
+
+ /**
+ * Returns size of stream in bytes.
+ * @return size of stream.
+ */
+ long length () throws IOException {
+ return control.getLength();
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java Wed Apr 18 09:17:01 2007
@@ -61,9 +61,11 @@
//randomly selected value
private final int MAX_BUF_SIZE = 4096;
private String dbName;
+ private long updateCount;
public LOBStreamControl (String dbName) {
this.dbName = dbName;
+ updateCount = 0;
}
private void init(byte [] b, long len) throws IOException, SQLException {
@@ -170,6 +172,7 @@
*/
synchronized long write(int b, long pos) throws IOException, SQLException {
isValidPostion(pos);
+ updateCount++;
if (isBytes) {
if (pos + 1 < MAX_BUF_SIZE) {
byte [] bytes = {(byte) b};
@@ -205,6 +208,7 @@
SQLState.BLOB_INVALID_OFFSET)))
throw new ArrayIndexOutOfBoundsException (e.getMessage());
}
+ updateCount++;
if (isBytes) {
if (pos + b.length < MAX_BUF_SIZE)
return updateData(b, off, len, pos);
@@ -368,5 +372,80 @@
throw (RuntimeException) e;
}
}
+ }
+
+ /**
+ * Replaces bytes in the middle of the lob.The new byte array may not be
+ * be of same length as the original bytes, so it may result in resizing
+ * the total length.
+ * @param buf byte array which will be written inplace of old block
+ * @param stPos starting pisition of old block
+ * @param endPos end position of old block
+ * @return newposition new write position
+ * @throws IOExcepton, SQLException
+ */
+ synchronized long replaceBytes (byte [] buf, long stPos, long endPos)
+ throws IOException, SQLException {
+ long length = getLength();
+ long finalLength = length - endPos + stPos + buf.length;
+ if (isBytes) {
+ if (finalLength > MAX_BUF_SIZE) {
+ init (dataBytes, stPos);
+ write (buf, 0, buf.length, getLength());
+ if (endPos < length)
+ write (dataBytes, (int) endPos,
+ (int) (length - endPos), getLength());
+ }
+ else {
+ byte [] tmpByte = new byte [(int) finalLength];
+ System.arraycopy (dataBytes, 0, tmpByte, 0, (int) stPos);
+ System.arraycopy (buf, 0, tmpByte, (int) stPos, (int) buf.length);
+ if (endPos < length)
+ System.arraycopy (dataBytes, (int) endPos, tmpByte,
+ (int) (stPos + buf.length), (int) (length - endPos));
+ dataBytes = tmpByte;
+ }
+ }
+ else {
+ //save over file handle and
+ //create new file with 0 size
+
+ byte tmp [] = new byte [0];
+ StorageRandomAccessFile oldFile = tmpFile;
+ init (tmp, 0);
+ byte [] tmpByte = new byte [1024];
+ long sz = stPos;
+ oldFile.seek(0);
+ while (sz != 0) {
+ int readLen = (int) Math.min (1024, sz);
+ int actualLength = oldFile.read (tmpByte, 0, readLen);
+ if (actualLength == -1)
+ break;
+ tmpFile.write (tmpByte, 0, actualLength);
+ sz -= actualLength;
+ }
+ tmpFile.write (buf);
+ oldFile.seek (endPos);
+ int rdLen;
+ if (endPos < length) {
+ do {
+ rdLen = oldFile.read (tmpByte, 0, 1024);
+ if (rdLen == -1)
+ break;
+ tmpFile.write (tmpByte, 0, rdLen);
+ }while (true);
+ }
+ }
+ updateCount++;
+ return stPos + buf.length;
+ }
+
+ /**
+ * Returns the running secquence number to check if the lob is updated since
+ * last access.
+ * @return newcount
+ */
+ long getUpdateCount() {
+ return updateCount;
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java Wed Apr 18 09:17:01 2007
@@ -66,6 +66,32 @@
this.utfLen = readUnsignedShort();
}
}
+
+ /**
+ * Constructs a UTF8Reader using a stream. This consturctor accepts
+ * the stream size as paramater and doesn't attempts to read the lenght
+ * from the stream.
+ * @param in InputStream
+ * @param maxFieldSize
+ * @param streamSize size of the stream
+ * @param parent connectionChild this stream is associated with
+ * @param synchronization object to synchronize on
+ * @throws IOException
+ */
+ public UTF8Reader(
+ InputStream in,
+ long maxFieldSize,
+ long streamSize,
+ ConnectionChild parent,
+ Object synchronization)
+ throws IOException {
+ super(synchronization);
+
+ this.in = in;
+ this.maxFieldSize = maxFieldSize;
+ this.parent = parent;
+ this.utfLen = streamSize;
+ }
/*
** Reader implemention.
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java Wed Apr 18 09:17:01 2007
@@ -1227,7 +1227,6 @@
rs.close();
stmt.close();
commit();
-
// no problem accessing this after commit since it is in memory
assertEquals("FAIL - can not access short clob after commit",
26, shortClob.length());
@@ -1313,9 +1312,19 @@
commit();
getConnection().close();
- // no problem accessing this after commit since it is in memory
- assertEquals("FAIL - erorr accessing short lob after closing the " +
- "connection", 26, shortClob.length());
+ try {
+ long len = shortClob.length();
+ if (usingEmbedded()) {
+ fail("FAIL - should not be able to access large log " +
+ "after commit");
+ }
+ assertEquals ("FAIL length mismatch", 26, len);
+ }
+ catch (SQLException e) {
+ checkException(NO_CURRENT_CONNECTION, e);
+ assertTrue("FAIL - Derby Client and JCC should not get an " +
+ "exception", usingEmbedded());
+ }
// these should all give blob/clob data unavailable exceptions
try {
@@ -1350,11 +1359,7 @@
"after the connection is closed");
}
} catch (SQLException e) {
- if (usingEmbedded()) {
- checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
- } else {
- checkException(NO_CURRENT_CONNECTION, e);
- }
+ checkException(NO_CURRENT_CONNECTION, e);
}
try {
clob.position(clob,2);
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobUpdateableReaderTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobUpdateableReaderTest.java?view=auto&rev=530085
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobUpdateableReaderTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobUpdateableReaderTest.java Wed Apr 18 09:17:01 2007
@@ -0,0 +1,166 @@
+/*
+ *
+ * Derby - Class ClobUpdateableReaderTest
+ *
+ * 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.derbyTesting.functionTests.tests.jdbcapi;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import junit.framework.Test;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test class to test Updateable Reader for Clob in embedder driver.
+ */
+public class ClobUpdateableReaderTest extends BaseJDBCTestCase {
+
+ private final String dummy = "This is a new String";
+
+ public ClobUpdateableReaderTest (String name) {
+ super (name);
+ }
+
+ /**
+ * Tests updates on reader.
+ */
+ public void testUpdateableReader () throws Exception {
+ Connection con = getConnection();
+ try {
+ con.setAutoCommit (false);
+ PreparedStatement ps = con.prepareStatement ("insert into updateClob " +
+ "(id , data) values (? ,?)");
+ ps.setInt (1, 1);
+ StringBuffer sb = new StringBuffer ();
+ String base = "SampleSampleSample";
+ for (int i = 0; i < 100; i++) {
+ sb.append (base);
+ }
+ ps.setCharacterStream (2, new StringReader (sb.toString()),
+ sb.length());
+ ps.execute();
+ ps.close();
+ Statement stmt = con.createStatement ();
+ ResultSet rs = stmt.executeQuery("select data from " +
+ "updateClob where id = 1");
+ rs.next();
+ Clob clob = rs.getClob (1);
+ rs.close();
+ stmt.close();
+ assertEquals (sb.length(), clob.length());
+ Reader r = clob.getCharacterStream();
+ char [] clobData = new char [sb.length()];
+ r.read (clobData);
+ assertEquals ("mismatch from inserted string",
+ String.valueOf (clobData), sb.toString());
+ r.close();
+ //update before gettting the reader
+ clob.setString (50, dummy);
+ r = clob.getCharacterStream();
+ r.skip (49);
+ char [] newChars = new char [dummy.length()];
+ r.read (newChars);
+ assertEquals ("update not reflected", dummy,
+ String.valueOf (newChars));
+ //update again and see if stream is refreshed
+ clob.setString (75, dummy);
+ r.skip (75 - 50 - dummy.length());
+ char [] testChars = new char [dummy.length()];
+ r.read (testChars);
+ assertEquals ("update not reflected", dummy,
+ String.valueOf (newChars));
+ r.close();
+ //try inserting some unicode string
+ String unicodeStr = getUnicodeString();
+ clob.setString (50, unicodeStr);
+ char [] utf16Chars = new char [unicodeStr.length()];
+ r = clob.getCharacterStream();
+ r.skip(49);
+ r.read(utf16Chars);
+ assertEquals ("update not reflected", unicodeStr,
+ String.valueOf (utf16Chars));
+ r.close();
+ Writer w = clob.setCharacterStream (1);
+ //write enough data to switch the data to file
+ r = clob.getCharacterStream ();
+ for (int i = 0; i < 10000; i++) {
+ w.write (dummy);
+ }
+ w.close();
+ clob.setString (500, unicodeStr);
+ r.skip (499);
+ char [] unicodeChars = new char [unicodeStr.length()];
+ r.read (unicodeChars);
+ assertEquals ("update not reflected", unicodeStr,
+ String.valueOf (unicodeChars));
+ }
+ finally {
+ if (con != null) {
+ con.commit ();
+ con.close();
+ }
+ }
+ }
+
+ private String getUnicodeString () {
+ char[] fill = new char[4];
+ fill[0] = 'd'; // 1 byte UTF8 character (ASCII)
+ fill[1] = '\u03a9'; // 2 byte UTF8 character (Greek)
+ fill[2] = '\u0e14'; // 3 byte UTF8 character (Thai)
+ fill[3] = 'j'; // 1 byte UTF8 character (ASCII)
+ StringBuffer sb = new StringBuffer ();
+ for (int i = 0; i < 4; i++) {
+ sb.append (fill);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Setup the test.
+ * @throws a SQLException.
+ */
+ public void setUp() throws Exception {
+ Connection con = getConnection ();
+ Statement stmt = con.createStatement ();
+ stmt.execute ("create table updateClob " +
+ "(id integer primary key, data clob)");
+ stmt.close();
+ con.commit();
+ con.close();
+ }
+
+ public static Test suite() {
+ return TestConfiguration.embeddedSuite(
+ ClobUpdateableReaderTest.class);
+ }
+
+ protected void tearDown() throws java.lang.Exception {
+ Connection con = getConnection ();
+ Statement stmt = con.createStatement ();
+ stmt.execute ("drop table updateClob");
+ stmt.close();
+ con.close();
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobUpdateableReaderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LobStreamsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LobStreamsTest.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LobStreamsTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LobStreamsTest.java Wed Apr 18 09:17:01 2007
@@ -19,6 +19,7 @@
*/
package org.apache.derbyTesting.functionTests.tests.jdbcapi;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
@@ -442,9 +443,27 @@
*/
public static Test suite() {
- return TestConfiguration.clientServerSuite(LobStreamsTest.class);
+ return TestConfiguration.defaultSuite (LobStreamsTest.class);
}
+ //method to ensure that buffer is filled if there is any data in stream
+ private int readBytesFromStream (byte [] b, InputStream is)
+ throws IOException {
+ int read = 0;
+ while (read < b.length) {
+ int ret = is.read (b, read, b.length - read);
+ if (ret < 0) {
+ if (read == 0) {
+ return ret;
+ }
+ else {
+ break;
+ }
+ }
+ read += ret;
+ }
+ return read;
+ }
private boolean compareLob2File(
InputStream fStream,
@@ -456,8 +475,8 @@
String fString, lString;
do {
- fLength = fStream.read(fByte, 0, 1024);
- lLength = lStream.read(lByte, 0, 1024);
+ fLength = readBytesFromStream (fByte, fStream);
+ lLength = readBytesFromStream (lByte, lStream);
if (!java.util.Arrays.equals(fByte, lByte))
return false;
} while (fLength > 0 && lLength > 0);
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java?view=diff&rev=530085&r1=530084&r2=530085
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java Wed Apr 18 09:17:01 2007
@@ -108,6 +108,9 @@
// Test uses DriverManager, Pooled and XADataSources, and
// an inner class implements ConnectionEventListener.
suite.addTest(DataSourceTest.suite());
+
+ //suite to test updateable reader for clob in embedded driver
+ suite.addTest (ClobUpdateableReaderTest.suite());
}
return suite;