org.h2.jdbc.JdbcClob Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of h2-mvstore Show documentation
Show all versions of h2-mvstore Show documentation
Fork of h2database to maintain Java 8 compatibility
The newest version!
/*
* Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jdbc;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.message.TraceObject;
import org.h2.store.RangeReader;
import org.h2.util.IOUtils;
import org.h2.value.Value;
/**
* Represents a CLOB value.
*/
public final class JdbcClob extends JdbcLob implements NClob {
/**
* INTERNAL
* @param conn it belongs to
* @param value of
* @param state of the LOB
* @param id of the trace object
*/
public JdbcClob(JdbcConnection conn, Value value, State state, int id) {
super(conn, value, state, TraceObject.CLOB, id);
}
/**
* Returns the length.
*
* @return the length
*/
@Override
public long length() throws SQLException {
try {
debugCodeCall("length");
checkReadable();
if (value.getValueType() == Value.CLOB) {
long precision = value.getType().getPrecision();
if (precision > 0) {
return precision;
}
}
return IOUtils.copyAndCloseInput(value.getReader(), null, Long.MAX_VALUE);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* [Not supported] Truncates the object.
*/
@Override
public void truncate(long len) throws SQLException {
throw unsupported("LOB update");
}
/**
* Returns the input stream.
*
* @return the input stream
*/
@Override
public InputStream getAsciiStream() throws SQLException {
try {
debugCodeCall("getAsciiStream");
checkReadable();
String s = value.getString();
return IOUtils.getInputStreamFromString(s);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* [Not supported] Returns an output stream.
*/
@Override
public OutputStream setAsciiStream(long pos) throws SQLException {
throw unsupported("LOB update");
}
@Override
public Reader getCharacterStream() throws SQLException {
return super.getCharacterStream();
}
/**
* Get a writer to update the Clob. This is only supported for new, empty
* Clob objects that were created with Connection.createClob() or
* createNClob(). The Clob is created in a separate thread, and the object
* is only updated when Writer.close() is called. The position must be 1,
* meaning the whole Clob data is set.
*
* @param pos where to start writing (the first character is at position 1)
* @return a writer
*/
@Override
public Writer setCharacterStream(long pos) throws SQLException {
try {
if (isDebugEnabled()) {
debugCodeCall("setCharacterStream", pos);
}
checkEditable();
if (pos != 1) {
throw DbException.getInvalidValueException("pos", pos);
}
state = State.SET_CALLED;
return setCharacterStreamImpl();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns a substring.
*
* @param pos the position (the first character is at position 1)
* @param length the number of characters
* @return the string
*/
@Override
public String getSubString(long pos, int length) throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("getSubString(" + pos + ", " + length + ')');
}
checkReadable();
if (pos < 1) {
throw DbException.getInvalidValueException("pos", pos);
}
if (length < 0) {
throw DbException.getInvalidValueException("length", length);
}
StringWriter writer = new StringWriter(
Math.min(Constants.IO_BUFFER_SIZE, length));
try (Reader reader = value.getReader()) {
IOUtils.skipFully(reader, pos - 1);
IOUtils.copyAndCloseInput(reader, writer, length);
}
return writer.toString();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Fills the Clob. This is only supported for new, empty Clob objects that
* were created with Connection.createClob() or createNClob(). The position
* must be 1, meaning the whole Clob data is set.
*
* @param pos where to start writing (the first character is at position 1)
* @param str the string to add
* @return the length of the added text
* @throws SQLException on failure
*/
@Override
public int setString(long pos, String str) throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("setString(" + pos + ", " + quote(str) + ')');
}
checkEditable();
if (pos != 1) {
throw DbException.getInvalidValueException("pos", pos);
} else if (str == null) {
throw DbException.getInvalidValueException("str", str);
}
completeWrite(conn.createClob(new StringReader(str), -1));
return str.length();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Fills the Clob. This is only supported for new, empty Clob objects that
* were created with Connection.createClob() or createNClob(). The position
* must be 1, meaning the whole Clob data is set.
*
* @param pos where to start writing (the first character is at position 1)
* @param str the string to add
* @param offset the string offset
* @param len the number of characters to read
* @return the length of the added text
*/
@Override
public int setString(long pos, String str, int offset, int len)
throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("setString(" + pos + ", " + quote(str) + ", " + offset + ", " + len + ')');
}
checkEditable();
if (pos != 1) {
throw DbException.getInvalidValueException("pos", pos);
} else if (str == null) {
throw DbException.getInvalidValueException("str", str);
}
completeWrite(conn.createClob(new RangeReader(new StringReader(str), offset, len), -1));
return (int) value.getType().getPrecision();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* [Not supported] Searches a pattern and return the position.
*/
@Override
public long position(String pattern, long start) throws SQLException {
throw unsupported("LOB search");
}
/**
* [Not supported] Searches a pattern and return the position.
*/
@Override
public long position(Clob clobPattern, long start) throws SQLException {
throw unsupported("LOB search");
}
/**
* Returns the reader, starting from an offset.
*
* @param pos 1-based offset
* @param length length of requested area
* @return the reader
*/
@Override
public Reader getCharacterStream(long pos, long length) throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("getCharacterStream(" + pos + ", " + length + ')');
}
checkReadable();
if (state == State.NEW) {
if (pos != 1) {
throw DbException.getInvalidValueException("pos", pos);
}
if (length != 0) {
throw DbException.getInvalidValueException("length", pos);
}
}
return value.getReader(pos, length);
} catch (Exception e) {
throw logAndConvert(e);
}
}
}