/* Copyright (c) 2001-2009, 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.persist; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import org.hsqldb.Database; import org.hsqldb.DatabaseURL; import org.hsqldb.Error; import org.hsqldb.ErrorCode; import org.hsqldb.HsqlException; import org.hsqldb.Session; import org.hsqldb.Statement; import org.hsqldb.Table; import org.hsqldb.Types; import org.hsqldb.lib.HashMappedList; import org.hsqldb.lib.HsqlByteArrayInputStream; import org.hsqldb.lib.HsqlByteArrayOutputStream; import org.hsqldb.lib.LineGroupReader; import org.hsqldb.navigator.RowSetNavigator; import org.hsqldb.result.Result; import org.hsqldb.result.ResultLob; import org.hsqldb.result.ResultMetaData; import org.hsqldb.types.BlobData; import org.hsqldb.types.BlobDataID; import org.hsqldb.types.ClobData; import org.hsqldb.types.ClobDataID; /** * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 1.9.0 * @since 1.9.0 */ public class LobManager { static final String resourceFileName = "/org/hsqldb/resources/lob-schema.sql"; static final String[] starters = new String[]{ "/*" }; // Database database; LobStore lobStore; Session sysLobSession; // // int lobBlockSize = 1024 * 32; int totalBlockLimitCount = 1024 * 1024 * 1024; // Statement getLob; Statement getLobPart; Statement deleteLob; Statement deleteLobPart; Statement divideLobPart; Statement createLob; Statement createLobPart; Statement setLobLength; Statement setLobUsage; Statement getNextLobId; // LOBS columns private interface LOBS { int BLOCK_ADDR = 0; int BLOCK_COUNT = 1; int BLOCK_OFFSET = 2; int LOB_ID = 3; } private interface ALLOC_BLOCKS { int BLOCK_COUNT = 0; int BLOCK_OFFSET = 1; int LOB_ID = 2; } //BLOCK_ADDR INT, BLOCK_COUNT INT, TX_ID BIGINT private static String initialiseBlocksSQL = "INSERT INTO SYSTEM_LOBS.BLOCKS VALUES(?,?,?)"; private static String getLobSQL = "SELECT * FROM SYSTEM_LOBS.LOB_IDS WHERE LOB_ID = ?"; private static String getLobPartSQL = "SELECT * FROM SYSTEM_LOBS.LOBS WHERE LOB_ID = ? AND BLOCK_OFFSET >= ? AND BLOCK_OFFSET < ? ORDER BY BLOCK_OFFSET"; // DELETE_BLOCKS(L_ID BIGINT, B_OFFSET INT, B_COUNT INT, TX_ID BIGINT) private static String deleteLobPartSQL = "CALL SYSTEM_LOBS.DELETE_BLOCKS(?,?,?,?)"; private static String createLobSQL = "INSERT INTO SYSTEM_LOBS.LOB_IDS VALUES(?, ?, ?, ?)"; private static String updateLobLengthSQL = "UPDATE SYSTEM_LOBS.LOB_IDS SET LOB_LENGTH = ? WHERE LOB_ID = ?"; private static String createLobPartSQL = "CALL SYSTEM_LOBS.ALLOC_BLOCKS(?, ?, ?)"; private static String divideLobPartSQL = "CALL SYSTEM_LOBS.DIVIDE_BLOCK(?, ?)"; private static String getSpanningBlockSQL = "SELECT * FROM SYSTEM_LOBS.LOBS WHERE LOB_ID = ? AND ? > BLOCK_OFFSET AND ? < BLOCK_OFFSET + BLOCK_COUNT"; private static String updateLobUsageSQL = "UPDATE SYSTEM_LOBS.LOB_IDS SET LOB_USAGE_COUNT = ? WHERE LOB_ID = ?"; private static String getNextLobIdSQL = "VALUES NEXT VALUE FOR SYSTEM_LOBS.LOB_ID"; private static String deleteLobSQL = "CALL SYSTEM_LOBS.DELETE_LOB(?, ?)"; // (OUT L_ADDR INT, IN B_COUNT INT, IN B_OFFSET INT, IN L_ID BIGINT, IN L_LENGTH BIGINT) public LobManager(Database database) { this.database = database; } public void createSchema() { sysLobSession = database.sessionManager.getSysLobSession(); Session session = sysLobSession; InputStream fis = getClass().getResourceAsStream(resourceFileName); InputStreamReader reader = null; try { reader = new InputStreamReader(fis, "ISO-8859-1"); } catch (Exception e) {} LineNumberReader lineReader = new LineNumberReader(reader); LineGroupReader lg = new LineGroupReader(lineReader, starters); HashMappedList map = lg.getAsMap(); lg.close(); String sql = (String) map.get("/*lob_schema_definition*/"); Statement statement = session.compileStatement(sql); Result result = statement.execute(session); Table table = database.schemaManager.getTable(session, "BLOCKS", "SYSTEM_LOBS"); // table.isTransactional = false; getLob = session.compileStatement(getLobSQL); getLobPart = session.compileStatement(getLobPartSQL); createLob = session.compileStatement(createLobSQL); createLobPart = session.compileStatement(createLobPartSQL); divideLobPart = session.compileStatement(divideLobPartSQL); deleteLob = session.compileStatement(deleteLobSQL); deleteLobPart = session.compileStatement(deleteLobPartSQL); setLobLength = session.compileStatement(updateLobLengthSQL); setLobUsage = session.compileStatement(updateLobUsageSQL); getNextLobId = session.compileStatement(getNextLobIdSQL); } public void initialiseLobSpace() { Statement statement = sysLobSession.compileStatement(initialiseBlocksSQL); Object[] args = new Object[3]; args[0] = Integer.valueOf(0); args[1] = Integer.valueOf(totalBlockLimitCount); args[2] = Long.valueOf(0); sysLobSession.executeCompiledStatement(statement, args); } void initialiseLobStore() {} public void open() { if (DatabaseURL.isFileBasedDatabaseType(database.getType())) { lobStore = new LobStoreRAFile(database, lobBlockSize); } else { lobStore = new LobStoreMem(lobBlockSize); } } public void close() {} // private long getNewLobID(Session session) { Result result = getNextLobId.execute(session); if (result.isError()) { return 0; } RowSetNavigator navigator = result.getNavigator(); boolean next = navigator.next(); if (!next) { navigator.close(); return 0; } Object[] data = navigator.getCurrent(); return ((Long) data[0]).longValue(); } private Object[] getLobHeader(Session session, long lobID) { ResultMetaData meta = getLob.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); session.sessionContext.pushDynamicArguments(params); Result result = getLob.execute(session); session.sessionContext.popDynamicArguments(); if (result.isError()) { return null; } RowSetNavigator navigator = result.getNavigator(); boolean next = navigator.next(); if (!next) { navigator.close(); return null; } Object[] data = navigator.getCurrent(); return data; } public BlobData getBlob(Session session, long lobID) { Object[] data = getLobHeader(session, lobID); if (data == null) { return null; } BlobData blob = new BlobDataID(lobID); return blob; } public ClobData getClob(Session session, long lobID) { Object[] data = getLobHeader(session, lobID); if (data == null) { return null; } ClobData clob = new ClobDataID(lobID); return clob; } public long createBlob(long length) { long lobID = getNewLobID(sysLobSession); ResultMetaData meta = createLob.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Long.valueOf(length); params[2] = Long.valueOf(1); params[3] = Integer.valueOf(Types.SQL_BLOB); Result result = sysLobSession.executeCompiledStatement(createLob, params); return lobID; } public long createClob(long length) { long lobID = getNewLobID(sysLobSession); ResultMetaData meta = createLob.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Long.valueOf(length); params[2] = Long.valueOf(1); params[3] = Integer.valueOf(Types.SQL_CLOB); Result result = sysLobSession.executeCompiledStatement(createLob, params); return lobID; } public Result deleteLob(long lobID) { Session session = this.sysLobSession; ResultMetaData meta = deleteLob.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Long.valueOf(0); Result result = session.executeCompiledStatement(deleteLob, params); return result; } public Result getLength(Session session, long lobID) { try { long length = getLengthValue(session, lobID); return ResultLob.newLobSetResponse(lobID, length); } catch (HsqlException e) { return Result.newErrorResult(e); } } public long getLengthValue(Session session, long lobID) { Object[] data = getLobHeader(session, lobID); if (data == null) { throw Error.error(ErrorCode.X_0F502); } long length = ((Long) data[1]).longValue(); return length; } /** * Used for SUBSTRING */ public Result getLob(Session session, long lobID, long offset, long length) { throw Error.runtimeError(ErrorCode.U_S0500, "LobManager"); } public Result createDuplicateLob(Session session, long lobID) { Object[] data = getLobHeader(session, lobID); if (data == null) { Result.newErrorResult(Error.error(ErrorCode.X_0F502)); } long newLobID = getNewLobID(session); Object params[] = new Object[data.length]; params[0] = Long.valueOf(newLobID); params[1] = data[1]; params[2] = data[2]; params[3] = data[3]; Result result = session.executeCompiledStatement(createLob, params); if (result.isError()) { return result; } long length = ((Long) data[1]).longValue(); long byteLength = length; int lobType = ((Integer) data[1]).intValue(); if (lobType == Types.SQL_CLOB) { byteLength *= 2; } int newBlockCount = (int) byteLength / lobBlockSize; if (byteLength % lobBlockSize != 0) { newBlockCount++; } createBlockAddresses(session, newLobID, 0, newBlockCount); // copy the contents int[][] sourceBlocks = getBlockAddresses(session, lobID, 0, Integer.MAX_VALUE); int[][] targetBlocks = getBlockAddresses(session, newLobID, 0, Integer.MAX_VALUE); try { copyBlockSet(sourceBlocks, targetBlocks); } catch (HsqlException e) { return Result.newErrorResult(e); } return ResultLob.newLobSetResponse(newLobID, length); } private void copyBlockSet(int[][] source, int[][] target) { int sourceIndex = 0; int targetIndex = 0; while (true) { int sourceOffset = source[sourceIndex][LOBS.BLOCK_OFFSET] + sourceIndex; int targetOffset = target[targetIndex][LOBS.BLOCK_OFFSET] + targetIndex; byte[] bytes = lobStore.getBlockBytes(sourceOffset, 1); lobStore.setBlockBytes(bytes, targetOffset, 1); sourceOffset++; targetOffset++; if (sourceOffset == source[sourceIndex][LOBS.BLOCK_COUNT]) { sourceOffset = 0; sourceIndex++; } if (targetOffset == target[sourceIndex][LOBS.BLOCK_COUNT]) { targetOffset = 0; targetIndex++; } if (sourceIndex == source.length) { break; } } } public Result getChars(Session session, long lobID, long offset, int length) { Result result = getBytes(session, lobID, offset * 2, length * 2); if (result.isError()) { return result; } byte[] bytes = ((ResultLob) result).getByteArray(); HsqlByteArrayInputStream be = new HsqlByteArrayInputStream(bytes); char[] chars = new char[bytes.length / 2]; try { for (int i = 0; i < chars.length; i++) { chars[i] = be.readChar(); } } catch (Exception e) { return Result.newErrorResult(e); } return ResultLob.newLobGetCharsResponse(lobID, offset, chars); } public Result getBytes(Session session, long lobID, long offset, int length) { int blockOffset = (int) (offset / lobBlockSize); int byteBlockOffset = (int) (offset % lobBlockSize); int blockLimit = (int) ((offset + length) / lobBlockSize); int byteLimitOffset = (int) ((offset + length) % lobBlockSize); if (byteLimitOffset == 0) { byteLimitOffset = lobBlockSize; } else { blockLimit++; } int dataBytesPosition = 0; byte[] dataBytes = new byte[length]; int[][] blockAddresses = getBlockAddresses(session, lobID, blockOffset, blockLimit); if (blockAddresses.length == 0) { return Result.newErrorResult(Error.error(ErrorCode.X_0F502)); } // int i = 0; int blockCount = blockAddresses[i][1] - (blockAddresses[i][2] - blockOffset); if (blockAddresses[i][1] + blockAddresses[i][2] > blockLimit) { blockCount -= (blockAddresses[i][1] + blockAddresses[i][2] - blockLimit); } byte[] bytes; try { bytes = lobStore.getBlockBytes(blockAddresses[i][0] + blockOffset, blockCount); } catch (HsqlException e) { return Result.newErrorResult(e); } int subLength = lobBlockSize * blockCount - byteBlockOffset; if (subLength > length) { subLength = length; } System.arraycopy(bytes, byteBlockOffset, dataBytes, dataBytesPosition, subLength); dataBytesPosition += subLength; i++; for (; i < blockAddresses.length && dataBytesPosition < length; i++) { blockCount = blockAddresses[i][1]; if (blockAddresses[i][1] + blockAddresses[i][2] > blockLimit) { blockCount -= (blockAddresses[i][1] + blockAddresses[i][2] - blockLimit); } try { bytes = lobStore.getBlockBytes(blockAddresses[i][0], blockCount); } catch (HsqlException e) { return Result.newErrorResult(e); } subLength = lobBlockSize * blockCount; if (subLength > length - dataBytesPosition) { subLength = length - dataBytesPosition; } System.arraycopy(bytes, 0, dataBytes, dataBytesPosition, subLength); dataBytesPosition += subLength; } return ResultLob.newLobGetBytesResponse(lobID, offset, dataBytes); } public Result setBytesBA(Session session, long lobID, byte[] dataBytes, long offset, int length) { Object[] data = getLobHeader(session, lobID); if (data == null) { return Result.newErrorResult(Error.error(ErrorCode.X_0F502)); } long oldLength = ((Long) data[1]).longValue(); int blockOffset = (int) (offset / lobBlockSize); int byteBlockOffset = (int) (offset % lobBlockSize); int blockLimit = (int) ((offset + length) / lobBlockSize); int byteLimitOffset = (int) ((offset + length) % lobBlockSize); if (byteLimitOffset == 0) { byteLimitOffset = lobBlockSize; } else { blockLimit++; } int[][] blockAddresses = getBlockAddresses(session, lobID, blockOffset, blockLimit); byte[] newBytes = new byte[(blockLimit - blockOffset) * lobBlockSize]; if (blockAddresses.length > 0) { int blockAddress = blockAddresses[0][0] + (blockOffset - blockAddresses[0][2]); try { byte[] block = lobStore.getBlockBytes(blockAddress, 1); System.arraycopy(block, 0, newBytes, 0, lobBlockSize); if (blockAddresses.length > 1) { blockAddress = blockAddresses[blockAddresses.length - 1][0] + (blockLimit - blockAddresses[blockAddresses.length - 1][2] - 1); block = lobStore.getBlockBytes(blockAddress, 1); System.arraycopy(block, 0, newBytes, blockLimit - blockOffset - 1, lobBlockSize); } else if (blockLimit - blockOffset > 1) { blockAddress = blockAddresses[0][0] + (blockLimit - blockAddresses[0][2] - 1); block = lobStore.getBlockBytes(blockAddress, 1); System.arraycopy(block, 0, newBytes, (blockLimit - blockOffset - 1) * lobBlockSize, lobBlockSize); } } catch (HsqlException e) { return Result.newErrorResult(e); } // should turn into SP divideBlockAddresses(session, lobID, blockOffset); divideBlockAddresses(session, lobID, blockLimit); deleteBlockAddresses(session, lobID, blockOffset, blockLimit); } createBlockAddresses(session, lobID, blockOffset, blockLimit - blockOffset); System.arraycopy(dataBytes, 0, newBytes, byteBlockOffset, length); blockAddresses = getBlockAddresses(session, lobID, blockOffset, blockLimit); // try { for (int i = 0; i < blockAddresses.length; i++) { lobStore.setBlockBytes(newBytes, blockAddresses[i][0], blockAddresses[i][1]); } } catch (HsqlException e) { return Result.newErrorResult(e); } if (offset + length > oldLength) { oldLength = offset + length; setLength(session, lobID, oldLength); } return ResultLob.newLobSetResponse(lobID, 0); } private Result setBytesIS(Session session, long lobID, InputStream inputStream, long length) { int blockLimit = (int) (length / lobBlockSize); int byteLimitOffset = (int) (length % lobBlockSize); if (byteLimitOffset == 0) { byteLimitOffset = lobBlockSize; } else { blockLimit++; } createBlockAddresses(session, lobID, 0, blockLimit); int[][] blockAddresses = getBlockAddresses(session, lobID, 0, blockLimit); byte[] dataBytes = new byte[lobBlockSize]; for (int i = 0; i < blockAddresses.length; i++) { for (int j = 0; j < blockAddresses[i][1]; j++) { int localLength = lobBlockSize; if (i == blockAddresses.length - 1 && j == blockAddresses[i][1] - 1) { localLength = byteLimitOffset; // todo -- use block op for (int k = localLength; k < lobBlockSize; k++) { dataBytes[k] = 0; } } try { int count = 0; while (localLength > 0) { int read = inputStream.read(dataBytes, count, localLength); if (read == -1) { return Result.newErrorResult(new EOFException()); } localLength -= read; count += read; } // read more } catch (IOException e) { // deallocate return Result.newErrorResult(e); } try { lobStore.setBlockBytes(dataBytes, blockAddresses[i][0] + j, 1); } catch (HsqlException e) { return Result.newErrorResult(e); } } } return ResultLob.newLobSetResponse(lobID, 0); } public Result setBytes(Session session, long lobID, byte[] dataBytes, long offset) { if (dataBytes.length == 0) { return ResultLob.newLobSetResponse(lobID, 0); } Object[] data = getLobHeader(session, lobID); if (data == null) { return Result.newErrorResult(Error.error(ErrorCode.X_0F502)); } long length = ((Long) data[1]).longValue(); Result result = setBytesBA(session, lobID, dataBytes, offset, dataBytes.length); if (offset + dataBytes.length > length) { setLength(session, lobID, offset + dataBytes.length); } return result; } public Result setBytesForNewBlob(long lobID, InputStream inputStream, long length) { Session session = sysLobSession; if (length == 0) { return ResultLob.newLobSetResponse(lobID, 0); } Result result = setBytesIS(session, lobID, inputStream, length); return result; } public Result setChars(Session session, long lobID, long offset, char[] chars) { if (chars.length == 0) { return ResultLob.newLobSetResponse(lobID, 0); } Object[] data = getLobHeader(session, lobID); if (data == null) { return Result.newErrorResult(Error.error(ErrorCode.X_0F502)); } long length = ((Long) data[1]).longValue(); HsqlByteArrayOutputStream os = new HsqlByteArrayOutputStream(chars.length * 2); os.write(chars, 0, chars.length); Result result = setBytesBA(session, lobID, os.getBuffer(), offset * 2, os.getBuffer().length); if (result.isError()) { return result; } if (offset + chars.length > length) { result = setLength(session, lobID, offset + chars.length); if (result.isError()) { return result; } } return ResultLob.newLobSetResponse(lobID, 0); } public Result setCharsForNewClob(long lobID, InputStream inputStream, long length) { Session session = sysLobSession; if (length == 0) { return ResultLob.newLobSetResponse(lobID, 0); } Result result = setBytesIS(session, lobID, inputStream, length * 2); if (result.isError()) { return result; } return ResultLob.newLobSetResponse(lobID, 0); } public Result truncate(Session session, long lobID, long offset) { Object[] data = getLobHeader(session, lobID); if (data == null) { return Result.newErrorResult(Error.error(ErrorCode.X_0F502)); } /** @todo 1.9.0 - double offset for clob */ long length = ((Long) data[1]).longValue(); int blockOffset = (int) (offset / lobBlockSize); int blockLimit = (int) ((offset + length) / lobBlockSize); int byteLimitOffset = (int) ((offset + length) % lobBlockSize); if (byteLimitOffset != 0) { blockLimit++; } ResultMetaData meta = deleteLobPart.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Integer.valueOf(blockOffset); params[2] = Integer.valueOf(blockLimit); params[3] = Long.valueOf(session.getTransactionTimestamp()); Result result = session.executeCompiledStatement(deleteLobPart, params); setLength(session, lobID, offset); return ResultLob.newLobTruncateResponse(lobID); } public Result setLength(Session session, long lobID, long length) { ResultMetaData meta = setLobLength.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(length); params[1] = Long.valueOf(lobID); Result result = session.executeCompiledStatement(setLobLength, params); return result; } public Result adjustUsageCount(long lobID, int delta) { Object[] data = getLobHeader(sysLobSession, lobID); int count = ((Number) data[2]).intValue(); if (count + delta == 0) { return deleteLob(lobID); } ResultMetaData meta = setLobUsage.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(count + delta); params[1] = Long.valueOf(lobID); Result result = sysLobSession.executeCompiledStatement(setLobLength, params); return result; } int[][] getBlockAddresses(Session session, long lobID, int offset, int limit) { ResultMetaData meta = getLobPart.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Integer.valueOf(offset); params[2] = Integer.valueOf(limit); session.sessionContext.pushDynamicArguments(params); Result result = getLobPart.execute(session); session.sessionContext.popDynamicArguments(); RowSetNavigator navigator = result.getNavigator(); int size = navigator.getSize(); int[][] blocks = new int[size][3]; for (int i = 0; i < size; i++) { navigator.absolute(i); Object[] data = navigator.getCurrent(); blocks[i][0] = ((Integer) data[LOBS.BLOCK_ADDR]).intValue(); blocks[i][1] = ((Integer) data[LOBS.BLOCK_COUNT]).intValue(); blocks[i][2] = ((Integer) data[LOBS.BLOCK_OFFSET]).intValue(); } navigator.close(); return blocks; } void deleteBlockAddresses(Session session, long lobID, int offset, int count) { ResultMetaData meta = deleteLobPart.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Integer.valueOf(offset); params[2] = Integer.valueOf(count); Result result = session.executeCompiledStatement(deleteLobPart, params); } void divideBlockAddresses(Session session, long lobID, int offset) { ResultMetaData meta = divideLobPart.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[0] = Long.valueOf(lobID); params[1] = Integer.valueOf(offset); Result result = session.executeCompiledStatement(divideLobPart, params); } void createBlockAddresses(Session session, long lobID, int offset, int count) { ResultMetaData meta = createLobPart.getParametersMetaData(); Object params[] = new Object[meta.getColumnCount()]; params[ALLOC_BLOCKS.BLOCK_COUNT] = Integer.valueOf(count); params[ALLOC_BLOCKS.BLOCK_OFFSET] = Integer.valueOf(offset); params[ALLOC_BLOCKS.LOB_ID] = Long.valueOf(lobID); Result result = session.executeCompiledStatement(createLobPart, params); } }