org.hsqldb.jdbc.JDBCClob Maven / Gradle / Ivy
/* Copyright (c) 2001-2011, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb.jdbc;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.sql.Clob;
import java.sql.SQLException;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.KMPSearchAlgorithm;
import org.hsqldb.lib.java.JavaSystem;
/* $Id: JDBCClob.java 5233 2013-05-06 12:58:11Z fredt $ */
// boucherb@users 2004-03/04-xx - doc 1.7.2 - javadocs updated; methods put in
// correct (historical, interface
// declared) order
// boucherb@users 2004-03/04-xx - patch 1.7.2 - null check for constructor (a
// null CLOB value is Java null,
// not a Clob object with null
// data);moderate thread safety;
// simplification; optimization
// of operations between jdbcClob
// instances
// boucherb@users 2005-12-07 - patch 1.8.0.x - initial JDBC 4.0 support work
// boucherb@users 2006-05-22 - doc 1.9.0 - full synch up to Mustang Build 84
// - patch 1.9.0 - setAsciiStream &
// setCharacterStream improvement
// patch 1.9.0
// - full synch up to Mustang b90
// - better bounds checking
/**
* The mapping in the JavaTM programming language
* for the SQL CLOB
type.
* An SQL CLOB
is a built-in type
* that stores a Character Large Object as a column value in a row of
* a database table.
* By default drivers implement a Clob
object using an SQL
* locator(CLOB)
, which means that a Clob
object
* contains a logical pointer to the SQL CLOB
data rather than
* the data itself. A Clob
object is valid for the duration
* of the transaction in which it was created.
* The Clob
interface provides methods for getting the
* length of an SQL CLOB
(Character Large Object) value,
* for materializing a CLOB
value on the client, and for
* searching for a substring or CLOB
object within a
* CLOB
value.
* Methods in the interfaces {@link java.sql.ResultSet},
* {@link java.sql.CallableStatement}, and {@link java.sql.PreparedStatement}, such as
* getClob
and setClob
allow a programmer to
* access an SQL CLOB
value. In addition, this interface
* has methods for updating a CLOB
value.
*
* All methods on the Clob
interface must be fully implemented if the
* JDBC driver supports the data type.
*
*
*
* HSQLDB-Specific Information:
*
* Previous to 2.0, the HSQLDB driver did not implement Clob using an SQL
* locator(CLOB). That is, an HSQLDB Clob object did not contain a logical
* pointer to SQL CLOB data; rather it directly contained a representation of
* the data (a String). As a result, an HSQLDB Clob object was itself
* valid beyond the duration of the transaction in which is was created,
* although it did not necessarily represent a corresponding value
* on the database. Also, the interface methods for updating a CLOB value
* were unsupported, with the exception of the truncate method,
* in that it could be used to truncate the local value.
*
* Starting with 2.0, the HSQLDB driver fully supports both local and remote
* SQL CLOB data implementations, meaning that an HSQLDB Clob object may
* contain a logical pointer to remote SQL CLOB data (see {@link JDBCClobClient
* JDBCClobClient}) or it may directly contain a local representation of the
* data (as implemented in this class). In particular, when the product is built
* under JDK 1.6+ and the Clob instance is constructed as a result of calling
* JDBCConnection.createClob(), then the resulting Clob instance is initially
* disconnected (is not bound to the transaction scope of the vending Connection
* object), the data is contained directly and all interface methods for
* updating the CLOB value are supported for local use until the first
* invocation of free(); otherwise, an HSQLDB Clob's implementation is
* determined at runtime by the driver, it is typically not valid beyond
* the duration of the transaction in which is was created, and there no
* standard way to query whether it represents a local or remote value.
*
*
*
*
* @author boucherb@users
* @version 2.3.0
* @since JDK 1.2, HSQLDB 1.7.2
* @revised JDK 1.6, HSQLDB 2.0
*/
public class JDBCClob implements Clob {
/**
* Retrieves the number of characters
* in the CLOB
value
* designated by this Clob
object.
*
* @return length of the CLOB
in characters
* @exception SQLException if there is an error accessing the
* length of the CLOB
value
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.2, HSQLDB 1.7.2
*/
public long length() throws SQLException {
return getData().length();
}
/**
* Retrieves a copy of the specified substring
* in the CLOB
value
* designated by this Clob
object.
* The substring begins at position
* pos
and has up to length
consecutive
* characters.
*
*
*
* HSQLDB-Specific Information:
*
* The official specification above is ambiguous in that it does not
* precisely indicate the policy to be observed when
* pos > this.length() - length. One policy would be to retrieve the
* characters from pos to this.length(). Another would be to throw
* an exception. HSQLDB observes the second policy.
*
* Note
*
* Depending java.lang.String implementation, the returned value
* may be sharing the underlying (and possibly much larger) character
* buffer. This facilitates much faster operation and will save memory
* if many transient substrings are to be retrieved during processing, but
* it has memory management implications should retrieved substrings be
* required to survive for any non-trivial duration. It is left up to the
* client to decide how to handle the trade-off (whether to make an isolated
* copy of the returned substring or risk that more memory remains allocated
* than is absolutely required).
*
*
*
* @param pos the first character of the substring to be extracted.
* The first character is at position 1.
* @param length the number of consecutive characters to be copied;
* JDBC 4.1[ the value for length must be 0 or greater]
* @return a String
that is the specified substring in
* the CLOB
value designated by this Clob
object
* @exception SQLException if there is an error accessing the
* CLOB
value; if pos is less than 1 JDBC 4.1[or length is
* less than 0]
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.2, HSQLDB 1.7.2
*/
public String getSubString(long pos,
final int length) throws SQLException {
final String data = getData();
final int dlen = data.length();
if (pos < MIN_POS || pos > dlen) {
JDBCUtil.outOfRangeArgument("pos: " + pos);
}
pos--;
if (length < 0 || length > dlen - pos) {
throw JDBCUtil.outOfRangeArgument("length: " + length);
}
return (pos == 0 && length == dlen) ? data
: data.substring((int) pos, (int) pos + length);
}
/**
* Retrieves the CLOB
value designated by this Clob
* object as a java.io.Reader
object (or as a stream of
* characters).
*
* @return a java.io.Reader
object containing the
* CLOB
data
* @exception SQLException if there is an error accessing the
* CLOB
value
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #setCharacterStream
* @since JDK 1.2, HSQLDB 1.7.2
*/
public java.io.Reader getCharacterStream() throws SQLException {
return new StringReader(getData());
}
/**
* Retrieves the CLOB
value designated by this Clob
* object as an ASCII stream.
*
* @return a java.io.InputStream
object containing the
* CLOB
data
* @exception SQLException if there is an error accessing the
* CLOB
value
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #setAsciiStream
* @since JDK 1.2, HSQLDB 1.7.2
*/
public java.io.InputStream getAsciiStream() throws SQLException {
try {
return new ByteArrayInputStream(getData().getBytes("US-ASCII"));
} catch (IOException e) {
return null;
}
}
/**
* Retrieves the character position at which the specified substring
* searchstr
appears in the SQL CLOB
value
* represented by this Clob
object. The search
* begins at position start
.
*
* @param searchstr the substring for which to search
* @param start the position at which to begin searching; the first position
* is 1
* @return the position at which the substring appears or -1 if it is not
* present; the first position is 1
* @exception SQLException if there is an error accessing the
* CLOB
value or if start is less than 1
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.2, HSQLDB 1.7.2
*/
public long position(final String searchstr,
long start) throws SQLException {
final String data = getData();
if (start < MIN_POS) {
throw JDBCUtil.outOfRangeArgument("start: " + start);
}
if (searchstr == null || start > MAX_POS) {
return -1;
}
final int position = KMPSearchAlgorithm.search(data, searchstr, null,
(int) start);
return (position == -1) ? -1
: position + 1;
}
/**
* Retrieves the character position at which the specified
* Clob
object searchstr
appears in this
* Clob
object. The search begins at position
* start
.
*
* @param searchstr the Clob
object for which to search
* @param start the position at which to begin searching; the first
* position is 1
* @return the position at which the Clob
object appears
* or -1 if it is not present; the first position is 1
* @exception SQLException if there is an error accessing the
* CLOB
value or if start is less than 1
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.2, HSQLDB 1.7.2
*/
public long position(final Clob searchstr,
long start) throws SQLException {
final String data = getData();
if (start < MIN_POS) {
throw JDBCUtil.outOfRangeArgument("start: " + start);
}
if (searchstr == null) {
return -1;
}
final long dlen = data.length();
final long sslen = searchstr.length();
start--;
// This is potentially much less expensive than materializing a large
// substring from some other vendor's CLOB. Indeed, we should probably
// do the comparison piecewise, using an in-memory buffer (or temp-files
// when available), if it is detected that the input CLOB is very long.
if (start > dlen - sslen) {
return -1;
}
// by now, we know sslen and start are both < Integer.MAX_VALUE
String pattern;
if (searchstr instanceof JDBCClob) {
pattern = ((JDBCClob) searchstr).data();
} else {
pattern = searchstr.getSubString(1L, (int) sslen);
}
final int position = KMPSearchAlgorithm.search(data, pattern, null,
(int) start);
return (position == -1) ? -1
: position + 1;
}
//---------------------------- jdbc 3.0 -----------------------------------
/**
* Writes the given Java String
to the CLOB
* value that this Clob
object designates at the position
* pos
. The string will overwrite the existing characters
* in the Clob
object starting at the position
* pos
. If the end of the Clob
value is reached
* while writing the given string, then the length of the Clob
* value will be increased to accommodate the extra characters.
*
* Note: If the value specified for pos
* is greater then the length+1 of the CLOB
value then the
* behavior is undefined. Some JDBC drivers may throw a
* SQLException
while other drivers may support this
* operation.
*
*
*
* HSQLDB-Specific Information:
*
* Starting with HSQLDB 2.0 this feature is supported.
*
* When built under JDK 1.6+ and the Clob instance is constructed as a
* result of calling JDBCConnection.createClob(), this operation affects
* only the client-side value; it has no effect upon a value stored in the
* database because JDBCConnection.createClob() constructs disconnected,
* initially empty Clob instances. To propagate the Clob value to a database
* in this case, it is required to supply the Clob instance to an updating
* or inserting setXXX method of a Prepared or Callable Statement, or to
* supply the Clob instance to an updateXXX method of an updateable
* ResultSet.
*
* Implementation Notes:
*
* No attempt is made to ensure precise thread safety. Instead, volatile
* member field and local variable snapshot isolation semantics are
* implemented. This is expected to eliminate most issues related
* to race conditions, with the possible exception of concurrent
* invocation of free().
*
* In general, however, if an application may perform concurrent
* JDBCClob modifications and the integrity of the application depends on
* total order Clob modification semantics, then such operations
* should be synchronized on an appropriate monitor.
*
*
*
*
* @param pos the position at which to start writing to the CLOB
* value that this Clob
object represents;
* The first position is 1
* @param str the string to be written to the CLOB
* value that this Clob
designates
* @return the number of characters written
* @exception SQLException if there is an error accessing the
* CLOB
value or if pos is less than 1
*
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.4, HSQLDB 1.7.2
* @revised JDK 1.6, HSQLDB 2.0
*/
public int setString(long pos, String str) throws SQLException {
if (str == null) {
throw JDBCUtil.nullArgument("str");
}
return setString(pos, str, 0, str.length());
}
/**
* Writes len
characters of str
, starting
* at character offset
, to the CLOB
value
* that this Clob
represents. The string will overwrite the existing characters
* in the Clob
object starting at the position
* pos
. If the end of the Clob
value is reached
* while writing the given string, then the length of the Clob
* value will be increased to accommodate the extra characters.
*
* Note: If the value specified for pos
* is greater then the length+1 of the CLOB
value then the
* behavior is undefined. Some JDBC drivers may throw a
* SQLException
while other drivers may support this
* operation.
*
*
*
* HSQLDB-Specific Information:
*
* Starting with HSQLDB 2.0 this feature is supported.
*
* When built under JDK 1.6+ and the Clob instance is constructed as a
* result of calling JDBCConnection.createClob(), this operation affects
* only the client-side value; it has no effect upon a value stored in a
* database because JDBCConnection.createClob() constructs disconnected,
* initially empty Clob instances. To propagate the Clob value to a database
* in this case, it is required to supply the Clob instance to an updating
* or inserting setXXX method of a Prepared or Callable Statement, or to
* supply the Clob instance to an updateXXX method of an updateable
* ResultSet.
*
* Implementation Notes:
*
* If the value specified for pos
* is greater than the length of the CLOB
value, then
* the CLOB
value is extended in length to accept the
* written characters and the undefined region up to pos
is
* filled with (char)0.
*
* No attempt is made to ensure precise thread safety. Instead, volatile
* member field and local variable snapshot isolation semantics are
* implemented. This is expected to eliminate most issues related
* to race conditions, with the possible exception of concurrent
* invocation of free().
*
* In general, however, if an application may perform concurrent
* JDBCClob modifications and the integrity of the application depends on
* total order Clob modification semantics, then such operations
* should be synchronized on an appropriate monitor.
*
*
*
*
* @param pos the position at which to start writing to this
* CLOB
object; The first position is 1
* @param str the string to be written to the CLOB
* value that this Clob
object represents
* @param offset the offset into str
to start reading
* the characters to be written
* @param len the number of characters to be written
* @return the number of characters written
* @exception SQLException if there is an error accessing the
* CLOB
value or if pos is less than 1
*
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.4, HSQLDB 1.7.2
* @revised JDK 1.6, HSQLDB 2.0
*/
public int setString(long pos, String str, int offset,
int len) throws SQLException {
if (!m_createdByConnection) {
/** @todo - better error message */
throw JDBCUtil.notSupported();
}
String data = getData();
if (str == null) {
throw JDBCUtil.nullArgument("str");
}
final int strlen = str.length();
if (offset < 0 || offset > strlen) {
throw JDBCUtil.outOfRangeArgument("offset: " + offset);
}
if (len > strlen - offset) {
throw JDBCUtil.outOfRangeArgument("len: " + len);
}
if (pos < MIN_POS || pos > 1L + (Integer.MAX_VALUE - len)) {
throw JDBCUtil.outOfRangeArgument("pos: " + pos);
}
final int dlen = data.length();
final int ipos = (int) (pos - 1);
StringBuffer sb;
if (ipos > dlen - len) {
sb = new StringBuffer(ipos + len);
sb.append(data.substring(0, ipos));
data = null;
sb.append(str.substring(offset, offset + len));
str = null;
} else {
sb = new StringBuffer(data);
data = null;
for (int i = ipos, j = 0; j < len; i++, j++) {
sb.setCharAt(i, str.charAt(offset + j));
}
str = null;
}
setData(sb.toString());
return len;
}
/**
* Retrieves a stream to be used to write ASCII characters to the
* CLOB
value that this Clob
object represents,
* starting at position pos
. Characters written to the stream
* will overwrite the existing characters
* in the Clob
object starting at the position
* pos
. If the end of the Clob
value is reached
* while writing characters to the stream, then the length of the Clob
* value will be increased to accommodate the extra characters.
*
* Note: If the value specified for pos
* is greater than the length of the CLOB
value, then the
* behavior is undefined. Some JDBC drivers may throw a
* SQLException
while other drivers may support this
* operation.
*
*
*
* HSQLDB-Specific Information:
*
* Starting with HSQLDB 2.0 this feature is supported.
*
* When built under JDK 1.6+ and the Clob instance is constructed as a
* result of calling JDBCConnection.createClob(), this operation affects
* only the client-side value; it has no effect upon a value stored in a
* database because JDBCConnection.createClob() constructs disconnected,
* initially empty Clob instances. To propagate the Clob value to a database
* in this case, it is required to supply the Clob instance to an updating
* or inserting setXXX method of a Prepared or Callable Statement, or to
* supply the Clob instance to an updateXXX method of an updateable
* ResultSet.
*
* Implementation Notes:
*
* The data written to the stream does not appear in this
* Clob until the stream is closed.
*
* When the stream is closed, if the value specified for pos
* is greater than the length of the CLOB
value, then
* the CLOB
value is extended in length to accept the
* written characters and the undefined region up to pos
is
* filled with (char)0.
*
* Also, no attempt is made to ensure precise thread safety. Instead,
* volatile member field and local variable snapshot isolation semantics
* are implemented. This is expected to eliminate most issues related
* to race conditions, with the possible exception of concurrent
* invocation of free().
*
* In general, however, if an application may perform concurrent
* JDBCClob modifications and the integrity of the application depends on
* total order Clob modification semantics, then such operations
* should be synchronized on an appropriate monitor.
*
*
*
*
* @param pos the position at which to start writing to this
* CLOB
object; The first position is 1
* @return the stream to which ASCII encoded characters can be written
* @exception SQLException if there is an error accessing the
* CLOB
value or if pos is less than 1
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getAsciiStream
*
* @since JDK 1.4, HSQLDB 1.7.2
* @revised JDK 1.6, HSQLDB 2.0
*/
public java.io.OutputStream setAsciiStream(
final long pos) throws SQLException {
if (!m_createdByConnection) {
/** @todo - Better error message */
throw JDBCUtil.notSupported();
}
checkClosed();
if (pos < MIN_POS || pos > MAX_POS) {
throw JDBCUtil.outOfRangeArgument("pos: " + pos);
}
return new java.io.ByteArrayOutputStream() {
public synchronized void close() throws java.io.IOException {
try {
JDBCClob.this.setString(pos,
new String(toByteArray(), "US-ASCII"));
} catch (SQLException se) {
throw JavaSystem.toIOException(se);
} finally {
super.close();
}
}
};
}
/**
* Retrieves a stream to be used to write a stream of Unicode characters
* to the CLOB
value that this Clob
object
* represents, at position pos
. Characters written to the stream
* will overwrite the existing characters
* in the Clob
object starting at the position
* pos
. If the end of the Clob
value is reached
* while writing characters to the stream, then the length of the Clob
* value will be increased to accommodate the extra characters.
*
* Note: If the value specified for pos
* is greater then the length+1 of the CLOB
value then the
* behavior is undefined. Some JDBC drivers may throw a
* SQLException
while other drivers may support this
* operation.
*
*
*
* HSQLDB-Specific Information:
*
* Starting with HSQLDB 2.0 this feature is supported.
*
* When built under JDK 1.6+ and the Clob instance is constructed as a
* result of calling JDBCConnection.createClob(), this operation affects
* only the client-side value; it has no effect upon a value stored in a
* database because JDBCConnection.createClob() constructs disconnected,
* initially empty Clob instances. To propagate the Clob value to a database
* in this case, it is required to supply the Clob instance to an updating
* or inserting setXXX method of a Prepared or Callable Statement, or to
* supply the Clob instance to an updateXXX method of an updateable
* ResultSet.
*
* Implementation Notes:
*
* The data written to the stream does not appear in this
* Clob until the stream is closed.
*
* When the stream is closed, if the value specified for pos
* is greater than the length of the CLOB
value, then
* the CLOB
value is extended in length to accept the
* written characters and the undefined region up to pos
is
* filled with (char)0.
*
* Also, no attempt is made to ensure precise thread safety. Instead,
* volatile member field and local variable snapshot isolation semantics
* are implemented. This is expected to eliminate most issues related
* to race conditions, with the possible exception of concurrent
* invocation of free().
*
* In general, however, if an application may perform concurrent
* JDBCClob modifications and the integrity of the application depends on
* total order Clob modification semantics, then such operations
* should be synchronized on an appropriate monitor.
*
*
*
*
* @param pos the position at which to start writing to the
* CLOB
value; The first position is 1
*
* @return a stream to which Unicode encoded characters can be written
* @exception SQLException if there is an error accessing the
* CLOB
value or if pos is less than 1
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getCharacterStream
*
* @since JDK 1.4, HSQLDB 1.7.2
* @revised JDK 1.6, HSQLDB 2.0
*/
public java.io.Writer setCharacterStream(
final long pos) throws SQLException {
if (!m_createdByConnection) {
/** @todo - better error message */
throw JDBCUtil.notSupported();
}
checkClosed();
if (pos < MIN_POS || pos > MAX_POS) {
throw JDBCUtil.outOfRangeArgument("pos: " + pos);
}
return new java.io.StringWriter() {
public synchronized void close() throws java.io.IOException {
try {
JDBCClob.this.setString(pos, toString());
} catch (SQLException se) {
throw JavaSystem.toIOException(se);
}
}
};
}
/**
* Truncates the CLOB
value that this Clob
* designates to have a length of len
* characters.
*
* Note: If the value specified for len
* is greater than the length of the CLOB
value, then the
* behavior is undefined. Some JDBC drivers may throw a
* SQLException
while other drivers may support this
* operation.
*
*
*
* HSQLDB-Specific Information:
*
* Starting with HSQLDB 2.0 this feature is fully supported.
*
* When built under JDK 1.6+ and the Clob instance is constructed as a
* result of calling JDBCConnection.createClob(), this operation affects
* only the client-side value; it has no effect upon a value stored in a
* database because JDBCConnection.createClob() constructs disconnected,
* initially empty Blob instances. To propagate the truncated Clob value to
* a database in this case, it is required to supply the Clob instance to
* an updating or inserting setXXX method of a Prepared or Callable
* Statement, or to supply the Blob instance to an updateXXX method of an
* updateable ResultSet.
*
* Implementation Notes:
*
* HSQLDB throws an SQLException if the specified len is greater
* than the value returned by {@link #length() length}.
*
*
*
*
* @param len the length, in characters, to which the CLOB
value
* should be truncated
* @exception SQLException if there is an error accessing the
* CLOB
value or if len is less than 0
*
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.4, HSQLDB 1.7.2
* @revised JDK 1.6, HSQLDB 2.0
*/
public void truncate(final long len) throws SQLException {
final String data = getData();
final long dlen = data.length();
if (!m_createdByConnection) {
/** @todo - better error message */
throw JDBCUtil.notSupported();
}
if (len == dlen) {
// nothing has changed, so there's nothing to be done
} else if (len < 0 || len > dlen) {
throw JDBCUtil.outOfRangeArgument("len: " + len);
} else {
// no need to get rid of slack
setData(data.substring(0, (int) len));
}
}
//------------------------- JDBC 4.0 -----------------------------------
/**
* This method frees the Clob
object and releases the resources the resources
* that it holds. The object is invalid once the free
method
* is called.
*
* After free
has been called, any attempt to invoke a
* method other than free
will result in a SQLException
* being thrown. If free
is called multiple times, the subsequent
* calls to free
are treated as a no-op.
*
* @throws SQLException if an error occurs releasing
* the Clob's resources
*
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.6, HSQLDB 2.0
*/
public synchronized void free() throws SQLException {
m_closed = true;
m_data = null;
}
/**
* Returns a Reader
object that contains a partial Clob
value, starting
* with the character specified by pos, which is length characters in length.
*
* @param pos the offset to the first character of the partial value to
* be retrieved. The first character in the Clob is at position 1.
* @param length the length in characters of the partial value to be retrieved.
* @return Reader
through which the partial Clob
value can be read.
* @throws SQLException if pos is less than 1 or if pos is greater than the number of
* characters in the Clob
or if pos + length is greater than the number of
* characters in the Clob
*
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since JDK 1.6, HSQLDB 2.0
*/
public Reader getCharacterStream(long pos,
long length) throws SQLException {
if (length > Integer.MAX_VALUE) {
throw JDBCUtil.outOfRangeArgument("length: " + length);
}
return new StringReader(getSubString(pos, (int) length));
}
// ---------------------- internal implementation --------------------------
private static final long MIN_POS = 1L;
private static final long MAX_POS = 1L + (long) Integer.MAX_VALUE;
private boolean m_closed;
private String m_data;
private final boolean m_createdByConnection;
/**
* Constructs a new JDBCClob object wrapping the given character
* sequence.
*
* This constructor is used internally to retrieve result set values as
* Clob objects, yet it must be public to allow access from other packages.
* As such (in the interest of efficiency) this object maintains a reference
* to the given String object rather than making a copy and so it is
* gently suggested (in the interest of effective memory management) that
* external clients using this constructor either take pause to consider
* the implications or at least take care to provide a String object whose
* internal character buffer is not much larger than required to represent
* the value.
*
* @param data the character sequence representing the Clob value
* @throws SQLException if the argument is null
*/
public JDBCClob(final String data) throws SQLException {
if (data == null) {
throw JDBCUtil.nullArgument();
}
m_data = data;
m_createdByConnection = false;
}
protected JDBCClob() {
m_data = "";
m_createdByConnection = true;
}
protected synchronized void checkClosed() throws SQLException {
if (m_closed) {
throw JDBCUtil.sqlException(ErrorCode.X_07501);
}
}
protected String data() throws SQLException {
return getData();
}
private synchronized String getData() throws SQLException {
checkClosed();
return m_data;
}
private synchronized void setData(String data) throws SQLException {
checkClosed();
m_data = data;
}
}