/* Copyright (c) 2001-2019, 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.CharArrayReader;
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.FrameworkLogger;
import org.hsqldb.lib.java.JavaSystem;

/* $Id: JDBCClob.java 5968 2019-04-27 12:55:27Z fredt $ */

// campbell-burnet@users 2004-03/04-xx - doc 1.7.2 - javadocs updated; methods put in
//                                            correct (historical, interface
//                                            declared) order
// campbell-burnet@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
// campbell-burnet@users 2005-12-07    - patch 1.8.0.x - initial JDBC 4.0 support work
// campbell-burnet@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 Java™ 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 ResultSet, CallableStatement, and 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 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:Campbell Burnet (campbell-burnet@users dot sourceforge.net)
Version:2.5.0
Since:JDK 1.2, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * The mapping in the Java&trade; programming language for the SQL <code>CLOB</code> type. * An SQL <code>CLOB</code> 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 <code>Clob</code> object using an SQL * <code>locator(CLOB)</code>, which means that a <code>Clob</code> object * contains a logical pointer to the SQL <code>CLOB</code> data rather than * the data itself. A <code>Clob</code> object is valid for the duration * of the transaction in which it was created. * <P>The <code>Clob</code> interface provides methods for getting the * length of an SQL <code>CLOB</code> (Character Large Object) value, * for materializing a <code>CLOB</code> value on the client, and for * searching for a substring or <code>CLOB</code> object within a * <code>CLOB</code> value. * Methods in the interfaces {@link java.sql.ResultSet}, * {@link java.sql.CallableStatement}, and {@link java.sql.PreparedStatement}, such as * <code>getClob</code> and <code>setClob</code> allow a programmer to * access an SQL <code>CLOB</code> value. In addition, this interface * has methods for updating a <code>CLOB</code> value. * <p> * All methods on the <code>Clob</code> interface must be fully implemented if the * JDBC driver supports the data type. * * <!-- start Release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * 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. <p> * * Starting with 2.0, the HSQLDB driver fully supports both local and remote * SQL CLOB data implementations, meaning that an HSQLDB Clob object <em>may</em> * 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.<p> * * </div> * <!-- end release-specific documentation --> * * @author Campbell Burnet (campbell-burnet@users dot sourceforge.net) * @version 2.5.0 * @since JDK 1.2, HSQLDB 1.7.2 * @revised JDK 1.6, HSQLDB 2.0 */
public class JDBCClob implements Clob { private static final FrameworkLogger LOG = FrameworkLogger.getLog(JDBCClob.class);
Retrieves the number of characters in the CLOB value designated by this Clob object.
Throws:
Returns:length of the CLOB in characters
Since:JDK 1.2, HSQLDB 1.7.2
/** * Retrieves the number of characters * in the <code>CLOB</code> value * designated by this <code>Clob</code> object. * * @return length of the <code>CLOB</code> in characters * @exception SQLException if there is an error accessing the * length of the <code>CLOB</code> value * @exception java.sql.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. This class observes the second policy.

Note

This method uses String.substring(int, int).

Depending on implementation (typically JDK 6 and earlier releases), the returned value may be sharing the underlying (and possibly much larger) character buffer. Depending on factors such as hardware acceleration for array copies, the average length and number of sub-strings taken, and so on, this may or may not result in faster operation and non-trivial memory savings. On the other hand, Oracle / OpenJDK 7, it was decided that the memory leak implications outweigh the benefits of buffer sharing for most use cases on modern hardware.

It is left up to any client of this method to determine if this is a potential factor relative to the target runtime and to decide how to handle space-time trade-offs (i.e. whether to make an isolated copy of the returned substring or risk that more memory remains allocated than is absolutely required).

Params:
  • pos – the first character of the substring to be extracted. The first character is at position 1.
  • length – the number of consecutive characters to be copied; JDBC 4.1[ the value for length must be 0 or greater]
Throws:
Returns:a String that is the specified substring in the CLOB value designated by this Clob object
Since:JDK 1.2, HSQLDB 1.7.2
/** * Retrieves a copy of the specified substring * in the <code>CLOB</code> value * designated by this <code>Clob</code> object. * The substring begins at position * <code>pos</code> and has up to <code>length</code> consecutive * characters. * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * The official specification above is ambiguous in that it does not * precisely indicate the policy to be observed when * {@code pos > this.length() - length}. One policy would be to retrieve * the characters from {@code pos} to {@code this.length()}. Another would * be to throw an exception. This class observes the second policy. <p> * * <b>Note</b><p> * * This method uses {@link java.lang.String#substring(int, int)}. * <p> * Depending on implementation (typically JDK 6 and earlier releases), the * returned value may be sharing the underlying (and possibly much larger) * character buffer. Depending on factors such as hardware acceleration for * array copies, the average length and number of sub-strings taken, and so * on, this <em>may or may not</em> result in faster operation and * non-trivial memory savings. On the other hand, Oracle / OpenJDK 7, it * was decided that the memory leak implications outweigh the benefits * of buffer sharing for most use cases on modern hardware. * <p> * It is left up to any client of this method to determine if this is a * potential factor relative to the target runtime and to decide how to * handle space-time trade-offs (i.e. whether to make an isolated copy of * the returned substring or risk that more memory remains allocated than * is absolutely required). * </div> * <!-- end release-specific documentation --> * * @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 <code>String</code> that is the specified substring in * the <code>CLOB</code> value designated by this <code>Clob</code> object * @exception SQLException if there is an error accessing the * <code>CLOB</code> value; if pos is less than 1 JDBC 4.1[or length is * less than 0] * @exception java.sql.SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @since JDK 1.2, HSQLDB 1.7.2 */
public String getSubString(final long pos, final int length) throws SQLException { final String data = getData(); final int dlen = data.length(); if (pos == MIN_POS && length == dlen) { return data; } if (pos < MIN_POS || pos > dlen) { throw JDBCUtil.outOfRangeArgument("pos: " + pos); } final long index = pos - 1; if (length < 0 || length > dlen - index) { throw JDBCUtil.outOfRangeArgument("length: " + length); } return data.substring((int) index, (int) index + length); }
Retrieves the CLOB value designated by this Clob object as a java.io.Reader object (or as a stream of characters).
Throws:
See Also:
Returns:a java.io.Reader object containing the CLOB data
Since:JDK 1.2, HSQLDB 1.7.2
/** * Retrieves the <code>CLOB</code> value designated by this <code>Clob</code> * object as a <code>java.io.Reader</code> object (or as a stream of * characters). * * @return a <code>java.io.Reader</code> object containing the * <code>CLOB</code> data * @exception SQLException if there is an error accessing the * <code>CLOB</code> value * @exception java.sql.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.
Throws:
See Also:
Returns:a java.io.InputStream object containing the CLOB data
Since:JDK 1.2, HSQLDB 1.7.2
/** * Retrieves the <code>CLOB</code> value designated by this <code>Clob</code> * object as an ASCII stream. * * @return a <code>java.io.InputStream</code> object containing the * <code>CLOB</code> data * @exception SQLException if there is an error accessing the * <code>CLOB</code> value * @exception java.sql.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(JavaSystem.CS_US_ASCII)); } catch (Throwable e) { throw JDBCUtil.sqlException(e); } }
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.
Params:
  • searchstr – the substring for which to search
  • start – the position at which to begin searching; the first position is 1
Throws:
Returns:the position at which the substring appears or -1 if it is not present; the first position is 1
Since:JDK 1.2, HSQLDB 1.7.2
/** * Retrieves the character position at which the specified substring * <code>searchstr</code> appears in the SQL <code>CLOB</code> value * represented by this <code>Clob</code> object. The search * begins at position <code>start</code>. * * @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 * <code>CLOB</code> value or if start is less than 1 * @exception java.sql.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 = data.indexOf(searchstr, (int) start - 1); 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.
Params:
  • searchstr – the Clob object for which to search
  • start – the position at which to begin searching; the first position is 1
Throws:
Returns:the position at which the Clob object appears or -1 if it is not present; the first position is 1
Since:JDK 1.2, HSQLDB 1.7.2
/** * Retrieves the character position at which the specified * <code>Clob</code> object <code>searchstr</code> appears in this * <code>Clob</code> object. The search begins at position * <code>start</code>. * * @param searchstr the <code>Clob</code> 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 <code>Clob</code> object appears * or -1 if it is not present; the first position is 1 * @exception SQLException if there is an error accessing the * <code>CLOB</code> value or if start is less than 1 * @exception java.sql.SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @since JDK 1.2, HSQLDB 1.7.2 */
public long position(final Clob searchstr, final 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(); final long startIndex = start - 1; // 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 (startIndex > dlen - sslen) { return -1; } // by now, we know sslen and startIndex are both < Integer.MAX_VALUE String pattern; if (searchstr instanceof JDBCClob) { pattern = ((JDBCClob) searchstr).getData(); } else { pattern = searchstr.getSubString(1L, (int) sslen); } final int index = data.indexOf(pattern, (int) startIndex); return (index == -1) ? -1 : index + 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, 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.

When the value specified for pos is greater then the length+1, then the CLOB value is extended in length to accept the written characters and the undefined region up to @{code pos} is filled with with space (' ') characters.

Params:
  • pos – the position at which to start writing to the CLOB value that this Clob object represents; The first position is 1
  • str – the string to be written to the CLOB value that this Clob designates
Throws:
Returns:the number of characters written
Since:JDK 1.4, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * Writes the given Java <code>String</code> to the <code>CLOB</code> * value that this <code>Clob</code> object designates at the position * <code>pos</code>. The string will overwrite the existing characters * in the <code>Clob</code> object starting at the position * <code>pos</code>. If the end of the <code>Clob</code> value is reached * while writing the given string, then the length of the <code>Clob</code> * value will be increased to accommodate the extra characters. * <p> * <b>Note:</b> If the value specified for <code>pos</code> * is greater then the length+1 of the <code>CLOB</code> value then the * behavior is undefined. Some JDBC drivers may throw a * <code>SQLException</code> while other drivers may support this * operation. * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 2.0 this feature is supported. <p> * * 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. <p> * * <b>Implementation Notes:</b><p> * * 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(). <p> * * In general, 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.<p> * * When the value specified for <code>pos</code> is greater then the * length+1, then the CLOB value is extended in length to accept the * written characters and the undefined region up to @{code pos} is filled * with with space (' ') characters. * * * </div> * <!-- end release-specific documentation --> * * @param pos the position at which to start writing to the <code>CLOB</code> * value that this <code>Clob</code> object represents; * The first position is 1 * @param str the string to be written to the <code>CLOB</code> * value that this <code>Clob</code> designates * @return the number of characters written * @exception SQLException if there is an error accessing the * <code>CLOB</code> value or if pos is less than 1 * * @exception java.sql.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 { return setString(pos, str, 0, str == null ? 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 space (' ') characters.

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, 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.

Params:
  • pos – the position at which to start writing to this CLOB object; The first position is 1
  • str – the string to be written to the CLOB value that this Clob object represents
  • offset – the offset into str to start reading the characters to be written
  • len – the number of characters to be written
Throws:
Returns:the number of characters written
Since:JDK 1.4, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * Writes <code>len</code> characters of <code>str</code>, starting * at character <code>offset</code>, to the <code>CLOB</code> value * that this <code>Clob</code> represents. The string will overwrite the existing characters * in the <code>Clob</code> object starting at the position * <code>pos</code>. If the end of the <code>Clob</code> value is reached * while writing the given string, then the length of the <code>Clob</code> * value will be increased to accommodate the extra characters. * <p> * <b>Note:</b> If the value specified for <code>pos</code> * is greater then the length+1 of the <code>CLOB</code> value then the * behavior is undefined. Some JDBC drivers may throw a * <code>SQLException</code> while other drivers may support this * operation. * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 2.0 this feature is supported. <p> * * 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. <p> * * <b>Implementation Notes:</b><p> * * If the value specified for <code>pos</code> * is greater than the length of the <code>CLOB</code> value, then * the <code>CLOB</code> value is extended in length to accept the * written characters and the undefined region up to <code>pos</code> is * filled with space (' ') characters.<p> * * 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(). <p> * * In general, 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.<p> * * </div> * <!-- end release-specific documentation --> * * @param pos the position at which to start writing to this * <code>CLOB</code> object; The first position is 1 * @param str the string to be written to the <code>CLOB</code> * value that this <code>Clob</code> object represents * @param offset the offset into <code>str</code> 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 * <code>CLOB</code> value or if pos is less than 1 * * @exception java.sql.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(final long pos, final String str, final int offset, final int len) throws SQLException { checkReadonly(); final String data = getData(); if (str == null) { throw JDBCUtil.nullArgument("str"); } final int strlen = str.length(); final int dlen = data.length(); final int ipos = (int) (pos - 1); if (offset == 0 && len == strlen && ipos == 0 && len >= dlen) { setData(str); return len; } if (offset < 0 || offset > strlen) { throw JDBCUtil.outOfRangeArgument("offset: " + offset); } if (len < 0 || len > strlen - offset) { throw JDBCUtil.outOfRangeArgument("len: " + len); } if (pos < MIN_POS || (pos - MIN_POS) > (Integer.MAX_VALUE - len)) { throw JDBCUtil.outOfRangeArgument("pos: " + pos); } final long endPos = (pos + len); char[] chars; if (pos > dlen) { // 1.) 'datachars' + '\32\32\32...' + substring chars = new char[(int) endPos - 1]; data.getChars(0, dlen, chars, 0); for (int i = dlen; i < ipos; i++) { chars[i] = ' '; } str.getChars(offset, offset + len, chars, ipos); } else if (endPos > dlen) { // 2.) 'datach...' + substring chars = new char[(int) endPos - 1]; data.getChars(0, ipos, chars, 0); str.getChars(offset, offset + len, chars, ipos); } else { // 3.) 'dat' + substring + 'rs' chars = new char[dlen]; data.getChars(0, ipos, chars, 0); str.getChars(offset, offset + len, chars, ipos); final int dataOffset = ipos + len; data.getChars(dataOffset, dlen, chars, dataOffset); } setData(new String(chars)); 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 updatable 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 space (' ') characters.

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, 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.

Params:
  • pos – the position at which to start writing to this CLOB object; The first position is 1
Throws:
See Also:
Returns:the stream to which ASCII encoded characters can be written
Since:JDK 1.4, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * Retrieves a stream to be used to write ASCII characters to the * <code>CLOB</code> value that this <code>Clob</code> object represents, * starting at position <code>pos</code>. Characters written to the stream * will overwrite the existing characters * in the <code>Clob</code> object starting at the position * <code>pos</code>. If the end of the <code>Clob</code> value is reached * while writing characters to the stream, then the length of the <code>Clob</code> * value will be increased to accommodate the extra characters. * <p> * <b>Note:</b> If the value specified for <code>pos</code> * is greater than the length of the <code>CLOB</code> value, then the * behavior is undefined. Some JDBC drivers may throw a * <code>SQLException</code> while other drivers may support this * operation. * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 2.0 this feature is supported. <p> * * 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 updatable * ResultSet. <p> * * <b>Implementation Notes:</b><p> * * The data written to the stream does not appear in this * Clob until the stream is closed. <p> * * When the stream is closed, if the value specified for <code>pos</code> * is greater than the length of the <code>CLOB</code> value, then * the <code>CLOB</code> value is extended in length to accept the * written characters and the undefined region up to <code>pos</code> is * filled with space (' ') characters. <p> * * 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(). <p> * * In general, 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.<p> * * </div> * <!-- end release-specific documentation --> * * @param pos the position at which to start writing to this * <code>CLOB</code> 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 * <code>CLOB</code> value or if pos is less than 1 * @exception java.sql.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 { checkReadonly(); checkClosed(); if (pos < MIN_POS || pos > MAX_POS) { throw JDBCUtil.outOfRangeArgument("pos: " + pos); } return new java.io.ByteArrayOutputStream() { boolean closed = false; public synchronized void close() throws java.io.IOException { if (closed) { return; } closed = true; final byte[] bytes = super.buf; final int length = super.count; super.buf = null; super.count = 0; try { final String str = new String(bytes, 0, length, JavaSystem.CS_US_ASCII); JDBCClob.this.setString(pos, str); } catch (Throwable e) { throw JavaSystem.toIOException(e); } } }; }
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 space (' ') characters.

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, 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.

Params:
  • pos – the position at which to start writing to the CLOB value; The first position is 1
Throws:
See Also:
Returns:a stream to which Unicode encoded characters can be written
Since:JDK 1.4, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * Retrieves a stream to be used to write a stream of Unicode characters * to the <code>CLOB</code> value that this <code>Clob</code> object * represents, at position <code>pos</code>. Characters written to the stream * will overwrite the existing characters * in the <code>Clob</code> object starting at the position * <code>pos</code>. If the end of the <code>Clob</code> value is reached * while writing characters to the stream, then the length of the <code>Clob</code> * value will be increased to accommodate the extra characters. * <p> * <b>Note:</b> If the value specified for <code>pos</code> * is greater then the length+1 of the <code>CLOB</code> value then the * behavior is undefined. Some JDBC drivers may throw a * <code>SQLException</code> while other drivers may support this * operation. * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 2.0 this feature is supported. <p> * * 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. <p> * * <b>Implementation Notes:</b><p> * * The data written to the stream does not appear in this * Clob until the stream is closed. <p> * * When the stream is closed, if the value specified for <code>pos</code> * is greater than the length of the <code>CLOB</code> value, then * the <code>CLOB</code> value is extended in length to accept the * written characters and the undefined region up to <code>pos</code> is * filled with space (' ') characters. <p> * * 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(). <p> * * In general, 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.<p> * * </div> * <!-- end release-specific documentation --> * * @param pos the position at which to start writing to the * <code>CLOB</code> 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 * <code>CLOB</code> value or if {@code pos} is less than 1 * @exception java.sql.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 { checkReadonly(); checkClosed(); if (pos < MIN_POS || pos > MAX_POS) { throw JDBCUtil.outOfRangeArgument("pos: " + pos); } return new java.io.StringWriter() { private boolean closed = false; public synchronized void close() throws java.io.IOException { if (closed) { return; } closed = true; final StringBuffer sb = super.getBuffer(); try { JDBCClob.this.setStringBuffer(pos, sb, 0, sb.length()); } catch (SQLException se) { throw JavaSystem.toIOException(se); } finally { sb.setLength(0); sb.trimToSize(); } } }; }
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 length.

Params:
  • len – the length, in characters, to which the CLOB value should be truncated
Throws:
Since:JDK 1.4, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * Truncates the <code>CLOB</code> value that this <code>Clob</code> * designates to have a length of <code>len</code> * characters. * <p> * <b>Note:</b> If the value specified for <code>len</code> * is greater than the length of the <code>CLOB</code> value, then the * behavior is undefined. Some JDBC drivers may throw a * <code>SQLException</code> while other drivers may support this * operation. * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 2.0 this feature is fully supported. <p> * * 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. <p> * * <b>Implementation Notes:</b> <p> * * HSQLDB throws an SQLException if the specified <tt>len</tt> is greater * than the value returned by {@link #length() length}. <p> * * </div> * <!-- end release-specific documentation --> * * @param len the length, in characters, to which the <code>CLOB</code> value * should be truncated * @exception SQLException if there is an error accessing the * <code>CLOB</code> value or if len is less than 0 * * @exception java.sql.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 { checkReadonly(); final String data = getData(); final long dlen = data.length(); if (len == dlen) { return; } if (len < 0 || len > dlen) { throw JDBCUtil.outOfRangeArgument("len: " + len); } 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:
Since:JDK 1.6, HSQLDB 2.0
/** * This method frees the <code>Clob</code> object and releases the resources the resources * that it holds. The object is invalid once the <code>free</code> method * is called. * <p> * After <code>free</code> has been called, any attempt to invoke a * method other than <code>free</code> will result in a <code>SQLException</code> * being thrown. If <code>free</code> is called multiple times, the subsequent * calls to <code>free</code> are treated as a no-op. * <p> * @throws SQLException if an error occurs releasing * the Clob's resources * * @exception java.sql.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.
Params:
  • pos – the offset to the first character of the partial value to be retrieved. The first character in the Clob is at position 1.
  • length – the length in characters of the partial value to be retrieved.
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
  • SQLFeatureNotSupportedException – if the JDBC driver does not support this method
Returns:Reader through which the partial Clob value can be read.
Since:JDK 1.6, HSQLDB 2.0
/** * Returns a <code>Reader</code> object that contains a partial <code>Clob</code> 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 <code>Reader</code> through which the partial <code>Clob</code> value can be read. * @throws SQLException if pos is less than 1 or if pos is greater than the number of * characters in the <code>Clob</code> or if pos + length is greater than the number of * characters in the <code>Clob</code> * * @exception java.sql.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); } final String data = getData(); final int dlen = data.length(); if (pos == MIN_POS && length == dlen) { return new StringReader(data); } if (pos < MIN_POS || pos > dlen) { throw JDBCUtil.outOfRangeArgument("pos: " + pos); } final long startIndex = pos - 1; if (length < 0 || length > dlen - startIndex) { throw JDBCUtil.outOfRangeArgument("length: " + length); } final int endIndex = (int) (startIndex + length); // exclusive final char[] chars = new char[(int) length]; data.getChars((int) startIndex, endIndex, chars, 0); return new CharArrayReader(chars); } // ---------------------- 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, read-only 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.

Params:
  • data – the character sequence representing the Clob value
Throws:
/** * Constructs a new, read-only JDBCClob object wrapping the given character * sequence. <p> * * 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; }
Constructs a new, empty (zero-length), read/write JDBCClob object.
/** * Constructs a new, empty (zero-length), read/write JDBCClob object. */
protected JDBCClob() { m_data = ""; m_createdByConnection = true; } protected void checkReadonly() throws SQLException { if (!m_createdByConnection) { throw JDBCUtil.sqlException(ErrorCode.X_25006, "Clob is read-only"); } } protected synchronized void checkClosed() throws SQLException { if (m_closed) { throw JDBCUtil.sqlException(ErrorCode.X_07501); } } synchronized String getData() throws SQLException { checkClosed(); return m_data; } private synchronized void setData(String data) throws SQLException { checkClosed(); m_data = data; }
Behaviour is identical to setString(long, String, int, int).
Params:
  • pos – the position at which to start writing to this CLOB object; The first position is 1
  • sb – the buffer to be written to the CLOB value that this Clob object represents
  • offset – the offset into sb to start reading the characters to be written
  • len – the number of characters to be written
Throws:
  • SQLException – if there is an error accessing the CLOB value or if pos is less than 1
Returns:the number of characters written
/** * Behaviour is identical to {@link #setString(long, java.lang.String, int, int)}. * * @param pos the position at which to start writing to this * <code>CLOB</code> object; The first position is 1 * @param sb the buffer to be written to the <code>CLOB</code> * value that this <code>Clob</code> object represents * @param offset the offset into <code>sb</code> 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 * <code>CLOB</code> value or if pos is less than 1 */
public int setStringBuffer(final long pos, final StringBuffer sb, final int offset, final int len) throws SQLException { checkReadonly(); String data = getData(); if (sb == null) { throw JDBCUtil.nullArgument("sb"); } final int strlen = sb.length(); final int dlen = data.length(); final int ipos = (int) (pos - 1); if (offset == 0 && len == strlen && ipos == 0 && len >= dlen) { setData(sb.toString()); return len; } if (offset < 0 || offset > strlen) { throw JDBCUtil.outOfRangeArgument("offset: " + offset); } if (len > strlen - offset) { throw JDBCUtil.outOfRangeArgument("len: " + len); } if (pos < MIN_POS || (pos - MIN_POS) > (Integer.MAX_VALUE - len)) { throw JDBCUtil.outOfRangeArgument("pos: " + pos); } final long endPos = (pos + len); char[] chars; if (pos > dlen) { // 1.) 'datachars' + '\32\32\32...' + substring chars = new char[(int) endPos - 1]; data.getChars(0, dlen, chars, 0); for (int i = dlen; i < ipos; i++) { chars[i] = ' '; } sb.getChars(offset, offset + len, chars, ipos); } else if (endPos > dlen) { // 2.) 'datach...' + substring chars = new char[(int) endPos - 1]; data.getChars(0, ipos, chars, 0); sb.getChars(offset, offset + len, chars, ipos); } else { // 3.) 'dat' + substring + 'rs' chars = new char[dlen]; data.getChars(0, ipos, chars, 0); sb.getChars(offset, offset + len, chars, ipos); final int dataOffset = ipos + len; data.getChars(dataOffset, dlen, chars, dataOffset); } setData(new String(chars)); return len; } }