/** * 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> */ public Reader getCharacterStream(long pos, long length) throws SQLException // @sync { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free synchronized (locator_) // @sync { if (pos < 1 || (pos - 1 + length) > locator_.getMaxLength() || length < 0) // @pdc change parm check like getSubString { JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); } Reader r = null; try { // @xml3 if xml column, remove xml declaration via ConvTableReader r = new ConvTableReader( new AS400JDBCInputStream(locator_), converter_.getCcsid(), converter_.bidiStringType_, isXML_); // @xml3 r.skip(pos); return r; } catch (UnsupportedEncodingException e) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); return null; } catch (IOException e) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); return null; } } }
public void convertFromRawBytes( byte[] rawBytes, int offset, ConvTable ccsidConverter, boolean ignoreConversionErrors) throws SQLException { int locatorHandle = BinaryConverter.byteArrayToInt(rawBytes, offset); locator_.setHandle(locatorHandle); locator_.setColumnIndex(columnIndex_); // @J5A reset saved handle after setting new value savedObject_ = null; }
public String getString() throws SQLException { if (savedObject_ != null) // @loch { // @loch // get value from RS.updateX(value) doConversion(); // @loch truncated_ = 0; // @loch return value_; // @loch } // @loch DBLobData data = locator_.retrieveData(0, locator_.getMaxLength()); String value = converter_.byteArrayToString(data.getRawBytes(), data.getOffset(), data.getLength()); truncated_ = 0; // @pda make consistent with other SQLData Clob classes return value; }
/** * Writes a String to this CLOB, starting at position <i>position</i>. The CLOB will be truncated * after the last character written. * * @param position The position (1-based) in the CLOB where writes should start. * @param stringToWrite The string that will be written to the CLOB. * @return The number of characters that were written. * @exception SQLException If there is an error accessing the CLOB or if the position specified is * greater than the length of the CLOB. */ public int setString(long position, String stringToWrite) throws SQLException { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free synchronized (locator_) { int offset = (int) position - 1; if (offset < 0 || offset >= maxLength_ || stringToWrite == null) { throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); } // We will write as many chars as we can. If our internal char array // would overflow past the 2 GB boundary, we don't throw an error, we just // return the number of chars that were set. char[] charsToWrite = stringToWrite.toCharArray(); int newSize = offset + charsToWrite.length; if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. int numChars = newSize - offset; if (numChars != charsToWrite.length) { char[] temp = charsToWrite; charsToWrite = new char[newSize]; System.arraycopy(temp, 0, charsToWrite, 0, numChars); } // We don't really know if all of these chars can be written until we go to // the system, so we just return the char[] length as the number written. byte[] bytesToWrite = converter_.stringToByteArray(charsToWrite, 0, charsToWrite.length); locator_.writeData((long) offset, bytesToWrite, false); // @K1A return charsToWrite.length; } }
/** * Writes a String to this CLOB, starting at position <i>position</i> in the CLOB. The CLOB will * be truncated after the last character written. The <i>lengthOfWrite</i> characters written will * start from <i>offset</i> in the string that was provided by the application. * * @param position The position (1-based) in the CLOB where writes should start. * @param string The string that will be written to the CLOB. * @param offset The offset into string to start reading characters (0-based). * @param lengthOfWrite The number of characters to write. * @return The number of characters written. * @exception SQLException If there is an error accessing the CLOB value or if the position * specified is greater than the length of the CLOB. */ public int setString(long position, String string, int offset, int lengthOfWrite) throws SQLException { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free synchronized (locator_) { int clobOffset = (int) position - 1; if (clobOffset < 0 || clobOffset >= maxLength_ || string == null || offset < 0 || lengthOfWrite < 0 || (offset + lengthOfWrite) > string.length() || (clobOffset + lengthOfWrite) > maxLength_) { throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); } // We will write as many chars as we can. If our internal char array // would overflow past the 2 GB boundary, we don't throw an error, we just // return the number of chars that were set. int newSize = clobOffset + lengthOfWrite; if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. int numChars = newSize - clobOffset; int realLength = (numChars < lengthOfWrite ? numChars : lengthOfWrite); char[] charsToWrite = new char[realLength]; string.getChars(offset, offset + numChars, charsToWrite, 0); // @K2C // We don't really know if all of these chars can be written until we go to // the system, so we just return the char[] length as the number written. byte[] bytesToWrite = converter_.stringToByteArray(charsToWrite, 0, charsToWrite.length); locator_.writeData((long) clobOffset, bytesToWrite, false); // @k1A return charsToWrite.length; } }
/** * Constructs an AS400JDBCClobLocator object. The data for the CLOB will be retrieved as * requested, directly from the IBM i system, using the locator handle. * * @param locator The locator. * @param converter The text converter. */ AS400JDBCClobLocator( JDLobLocator locator, ConvTable converter, Object savedObject, int savedScale) { locator_ = locator; converter_ = converter; savedObject_ = savedObject; savedScale_ = savedScale; maxLength_ = locator_.getMaxLength(); }
/** * Returns the length of the current contents of the CLOB in characters. * * @return The length of the CLOB in characters. * @exception SQLException If an error occurs. */ public long length() throws SQLException { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free synchronized (locator_) { return locator_.getLength(); } }
// @pda jdbc40 public String getNString() throws SQLException { truncated_ = 0; outOfBounds_ = false; if (savedObject_ != null) // @loch { // @loch // get value from RS.updateX(value) doConversion(); // @loch truncated_ = 0; outOfBounds_ = false; // @loch return value_; // @loch } // @loch DBLobData data = locator_.retrieveData(0, locator_.getMaxLength()); String value = converter_.byteArrayToString(data.getRawBytes(), data.getOffset(), data.getLength()); return value; }
/** * Returns the handle to this CLOB locator in the database. * * @return The handle to this locator in the databaes. */ int getHandle() throws SQLException // @free called from rs.updateValue(), which in turn will throw exc back to // rs.updateX() caller { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free return locator_.getHandle(); }
// @CRS - This is only called from AS400JDBCPreparedStatement in one place. public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) throws SQLException { BinaryConverter.intToByteArray(locator_.getHandle(), rawBytes, offset); // Now we write our saved data to the system, because the prepared statement is being executed. // We used to write the data to the system on the call to set(), but this messed up // batch executes, since the host server only reserves temporary space for locator handles one // row at a time. // See the toObject() method in this class for more details. if (savedObject_ != null) writeToServer(); }
public byte[] getBytes() throws SQLException { if (savedObject_ != null) // @loch { // @loch // get value from RS.updateX(value) doConversion(); // @loch truncated_ = 0; outOfBounds_ = false; // @loch return value_; // @loch } // @loch int locatorLength = (int) locator_.getLength(); if (locatorLength == 0) return new byte[0]; DBLobData data = locator_.retrieveData(0, locatorLength); int actualLength = data.getLength(); byte[] bytes = new byte[actualLength]; System.arraycopy(data.getRawBytes(), data.getOffset(), bytes, 0, actualLength); truncated_ = 0; outOfBounds_ = false; return bytes; }
/** * This method frees the <code>Clob</code> object and releases the resources that it holds. The * object is invalid once the <code>free</code> method is called. If <code>free</code> is called * multiple times, the subsequent calls to <code>free</code> are treated as a no-op. * * @throws SQLException if an error occurs releasing the Clob's resources */ public void free() throws SQLException // @sync { if (locator_ == null) return; // no-op synchronized (locator_) // @sync { locator_.free(); locator_ = null; // @pda make objects available for GC converter_ = null; savedObject_ = null; cache_ = null; } }
/** * Returns part of the contents of the CLOB. * * @param position The position within the CLOB (1-based). * @param length The number of characters to return. * @return The contents. * @exception SQLException If the position is not valid, if the length is not valid, or an error * occurs. */ public String getSubString(long position, int length) throws SQLException { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free synchronized (locator_) { int offset = (int) position - 1; if (offset < 0 || length < 0 || (offset > length())) { JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); } int lengthToUse = (int) length() - offset; if (lengthToUse < 0) return ""; if (lengthToUse > length) lengthToUse = length; // @xml4 if xml column, remove xml declaration via ConvTableReader if (isXML_) { ConvTableReader r = null; try { r = new ConvTableReader( new AS400JDBCInputStream(locator_), converter_.getCcsid(), converter_.bidiStringType_, isXML_); // @xml4 r.skip(offset); // @xml4 ConvTableReader will already have skipped XML header if column is // XML type return r.read(lengthToUse); // @xml4 } catch (Exception e) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); return null; } finally { try { if (r != null) r.close(); } catch (Exception ee) { JDTrace.logException(this, "getSubString r.close() threw exception", ee); } } } DBLobData data = locator_.retrieveData(offset, lengthToUse); int actualLength = data.getLength(); return converter_.byteArrayToString(data.getRawBytes(), data.getOffset(), actualLength); } }
/** * Truncates this CLOB to a length of <i>lengthOfCLOB</i> characters. * * @param lengthOfCLOB The length, in characters, that this CLOB should be after truncation. * @exception SQLException If there is an error accessing the CLOB or if the length specified is * greater than the length of the CLOB. */ public void truncate(long lengthOfCLOB) throws SQLException { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free synchronized (locator_) { int length = (int) lengthOfCLOB; if (length < 0 || length > maxLength_) { JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); } // truncate_ = length; // The host server does not currently provide a way for us // to truncate the temp space used to hold the locator data, // so we just keep track of it ourselves. This should work, // since the temp space on the system should only be valid // within the scope of our transaction/connection. That means // there's no reason to go to the system to update the data, // since no other process can get at it. locator_.writeData(length, new byte[0], 0, 0, true); // @k1A } }
/** * Get the locator handle corresponding to this ClobLocator * * @throws SQLException */ public int getLocator() throws SQLException { if (locator_ == null) // @free JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @free return locator_.getHandle(); }
// This method actually writes the data to the system. private void writeToServer() throws SQLException { if (savedObject_ instanceof byte[]) { byte[] bytes = (byte[]) savedObject_; locator_.writeData(0, bytes, true); // @K1A } else if (savedObject_ instanceof InputStream) { int length = scale_; // hack to get the length into the set method // Need to write even if there are 0 bytes in case we are batching and // the host server reuses the same handle for the previous locator; otherwise, // we'll have data in the current row from the previous row. if (length == 0) { locator_.writeData(0, new byte[0], 0, 0, true); // @K1A } else if (length > 0) { InputStream stream = (InputStream) savedObject_; int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; byte[] byteBuffer = new byte[blockSize]; try { int totalBytesRead = 0; int bytesRead = stream.read(byteBuffer, 0, blockSize); while (bytesRead > -1 && totalBytesRead < length) { locator_.writeData( totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset. @K1A totalBytesRead += bytesRead; int bytesRemaining = length - totalBytesRead; if (bytesRemaining < blockSize) { blockSize = bytesRemaining; } bytesRead = stream.read(byteBuffer, 0, blockSize); } if (totalBytesRead < length) { // a length longer than the stream was specified JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else if (length == -2) // @readerlen new else-if block (read all data) { InputStream stream = (InputStream) savedObject_; int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; byte[] byteBuffer = new byte[blockSize]; try { int totalBytesRead = 0; int bytesRead = stream.read(byteBuffer, 0, blockSize); while (bytesRead > -1) { locator_.writeData( totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset. @K1A totalBytesRead += bytesRead; bytesRead = stream.read(byteBuffer, 0, blockSize); } } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } else if (JDUtilities.JDBCLevel_ >= 20 && savedObject_ instanceof Blob) // @H0A check for jdbc level to know if lobs exist { // @A1C // @G5A Start new code for updateable locator case to go through the Vectors // @G5A and update the blob copy when ResultSet.updateBlob() is called. boolean set = false; if (savedObject_ instanceof AS400JDBCBlobLocator) { AS400JDBCBlobLocator blob = (AS400JDBCBlobLocator) savedObject_; // Synchronize on a lock so that the user can't keep making updates // to the blob while we are taking updates off the vectors. synchronized (blob) { // See if we saved off our real object from earlier. if (blob.savedObject_ != null) { savedObject_ = blob.savedObject_; scale_ = blob.savedScale_; blob.savedObject_ = null; writeToServer(); return; } } } // @G5A If the code for updateable lob locators did not run, then run old code. if (!set) { Blob blob = (Blob) savedObject_; // @A1C int length = (int) blob.length(); byte[] data = blob.getBytes(1, length); locator_.writeData(0, data, 0, length, true); // @K1A } } else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } }
public void setHandle(int handle) { locator_.setHandle(handle); // @J5A reset savedObject after setting handle savedObject_ = null; }
public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) throws SQLException { int locatorHandle = BinaryConverter.byteArrayToInt(rawBytes, offset); locator_.setHandle(locatorHandle); locator_.setColumnIndex(columnIndex_); }
// @loch public int getHandle() { return locator_.getHandle(); }
public void setHandle(int handle) { locator_.setHandle(handle); }
// @loch method to temporary convert from object input to output before even going to host // (writeToServer() does the conversion needed before writing to host) // This will only be used when resultSet.updateX(obj1) is called followed by a obj2 = // resultSet.getX() // Purpose is to do a local type conversion from obj1 to obj2 like other non-locator lob types private void doConversion() throws SQLException { int length_ = scale_; if (length_ == -1) { try { // try to get length from locator length_ = (int) locator_.getLength(); } catch (Exception e) { } } try { Object object = savedObject_; if (savedObject_ instanceof String) { value_ = (String) object; } else if (object instanceof Reader) { if (length_ >= 0) { try { int blockSize = length_ < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length_ : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; Reader stream = (Reader) object; StringBuffer buf = new StringBuffer(); char[] charBuffer = new char[blockSize]; int totalCharsRead = 0; int charsRead = stream.read(charBuffer, 0, blockSize); while (charsRead > -1 && totalCharsRead < length_) { buf.append(charBuffer, 0, charsRead); totalCharsRead += charsRead; int charsRemaining = length_ - totalCharsRead; if (charsRemaining < blockSize) { blockSize = charsRemaining; } charsRead = stream.read(charBuffer, 0, blockSize); } value_ = buf.toString(); if (value_.length() < length_) { // a length longer than the stream was specified JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else if (length_ == -2) // @readerlen new else-if block (read all data) { try { int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; Reader stream = (Reader) object; StringBuffer buf = new StringBuffer(); char[] charBuffer = new char[blockSize]; int totalCharsRead = 0; int charsRead = stream.read(charBuffer, 0, blockSize); while (charsRead > -1) { buf.append(charBuffer, 0, charsRead); totalCharsRead += charsRead; charsRead = stream.read(charBuffer, 0, blockSize); } value_ = buf.toString(); } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } else if (object instanceof Clob) { Clob clob = (Clob) object; value_ = clob.getSubString(1, (int) clob.length()); } /* ifdef JDBC40 else if( object instanceof SQLXML ) { SQLXML xml = (SQLXML)object; value_ = xml.getString(); } endif */ else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } // Truncate if necessary. int valueLength = value_.length(); if (valueLength > maxLength_) { value_ = value_.substring(0, maxLength_); } } finally { // nothing } }
private void writeToServer() throws SQLException { try { Object object = savedObject_; if (object instanceof String) { String string = (String) object; int bidiStringType = settings_.getBidiStringType(); if (bidiStringType == -1) bidiStringType = converter_.bidiStringType_; BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType); // @KBA bidiConversionProperties.setBidiImplicitReordering( settings_.getBidiImplicitReordering()); // @KBA bidiConversionProperties.setBidiNumericOrderingRoundTrip( settings_.getBidiNumericOrdering()); // @KBA byte[] bytes = converter_.stringToByteArray( string, bidiConversionProperties); // @KBC changed to use bidiConversionProperties instead // of bidiStringType locator_.writeData(0L, bytes, true); // @K1C } else if (object instanceof Reader) { int length = scale_; // hack to get the length into the set method // Need to write even if there are 0 bytes in case we are batching and // the host server reuses the same handle for the previous locator; otherwise, // we'll have data in the current row from the previous row. if (length == 0) { locator_.writeData(0, new byte[0], 0, 0, true); // @K1C } else if (length > 0) { try { int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; int bidiStringType = settings_.getBidiStringType(); if (bidiStringType == -1) bidiStringType = converter_.bidiStringType_; BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType); // @KBA bidiConversionProperties.setBidiImplicitReordering( settings_.getBidiImplicitReordering()); // @KBA bidiConversionProperties.setBidiNumericOrderingRoundTrip( settings_.getBidiNumericOrdering()); // @KBA ReaderInputStream stream = new ReaderInputStream( (Reader) savedObject_, converter_.getCcsid(), bidiConversionProperties, blockSize); // @KBC changed to use bidiConversionProperties instead of // bidiStringType byte[] byteBuffer = new byte[blockSize]; int totalBytesRead = 0; int bytesRead = stream.read(byteBuffer, 0, blockSize); while (bytesRead > -1 && totalBytesRead < length) { locator_.writeData( (long) totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset. @K1C totalBytesRead += bytesRead; int bytesRemaining = length - totalBytesRead; if (bytesRemaining < blockSize) { blockSize = bytesRemaining; if (stream.available() == 0 && blockSize != 0) { stream.close(); // @scan1 stream = new ReaderInputStream( (Reader) savedObject_, converter_.getCcsid(), bidiConversionProperties, blockSize); // do this so we don't read more chars out of the Reader than // we have to. //@KBC changed to use bidiConversionProperties // instead of bidiStringType } } bytesRead = stream.read(byteBuffer, 0, blockSize); } stream.close(); // @scan1 if (totalBytesRead < length) { // a length longer than the stream was specified JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else if (length == -2) // @readerlen new else-if block (read all data) { try { // String readerStr = JDUtilities.readerToString((Reader)savedObject_); int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; int bidiStringType = settings_.getBidiStringType(); if (bidiStringType == -1) bidiStringType = converter_.bidiStringType_; BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType); // @KBA bidiConversionProperties.setBidiImplicitReordering( settings_.getBidiImplicitReordering()); // @KBA bidiConversionProperties.setBidiNumericOrderingRoundTrip( settings_.getBidiNumericOrdering()); // @KBA ReaderInputStream stream = new ReaderInputStream( (Reader) savedObject_, converter_.getCcsid(), bidiConversionProperties, blockSize); // @KBC changed to use bidiConversionProperties instead of // bidiStringType byte[] byteBuffer = new byte[blockSize]; int totalBytesRead = 0; int bytesRead = stream.read(byteBuffer, 0, blockSize); while (bytesRead > -1) { locator_.writeData( (long) totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset. @K1C totalBytesRead += bytesRead; bytesRead = stream.read(byteBuffer, 0, blockSize); } stream.close(); // @scan1 } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } else if (object instanceof InputStream) { int length = scale_; // hack to get the length into the set method // Need to write even if there are 0 bytes in case we are batching and // the host server reuses the same handle for the previous locator; otherwise, // we'll have data in the current row from the previous row. if (length == 0) { locator_.writeData(0, new byte[0], 0, 0, true); // @K1C } else if (length > 0) { InputStream stream = (InputStream) savedObject_; int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; byte[] byteBuffer = new byte[blockSize]; try { int totalBytesRead = 0; int bytesRead = stream.read(byteBuffer, 0, blockSize); while (bytesRead > -1 && totalBytesRead < length) { locator_.writeData( (long) totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset. @K1C totalBytesRead += bytesRead; int bytesRemaining = length - totalBytesRead; if (bytesRemaining < blockSize) { blockSize = bytesRemaining; } bytesRead = stream.read(byteBuffer, 0, blockSize); } if (totalBytesRead < length) { // a length longer than the stream was specified JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else if (length == -2) // @readerlen new else-if block (read all data) { InputStream stream = (InputStream) savedObject_; int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; byte[] byteBuffer = new byte[blockSize]; try { int totalBytesRead = 0; int bytesRead = stream.read(byteBuffer, 0, blockSize); while (bytesRead > -1) { locator_.writeData( (long) totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset. @K1C totalBytesRead += bytesRead; bytesRead = stream.read(byteBuffer, 0, blockSize); } } catch (IOException ie) { JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie); } } else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } else if (JDUtilities.JDBCLevel_ >= 20 && object instanceof Clob) // @H0A check for jdbc level to know if lobs exist { // @G5A Start new code for updateable locator case boolean set = false; if (object instanceof AS400JDBCClobLocator) { AS400JDBCClobLocator clob = (AS400JDBCClobLocator) object; // Synchronize on a lock so that the user can't keep making updates // to the clob while we are taking updates off the vectors. synchronized (clob) { // See if we saved off our real object from earlier. if (clob.savedObject_ != null) { savedObject_ = clob.savedObject_; scale_ = clob.savedScale_; clob.savedObject_ = null; writeToServer(); return; } } } // @G5A If the code for updateable lob locators did not run, then run old code. if (!set) { Clob clob = (Clob) object; int length = (int) clob.length(); String substring = clob.getSubString(1, length); locator_.writeData(0L, converter_.stringToByteArray(substring), 0, length, true); // @K1C set = true; } else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } /*ifdef JDBC40 else if( object instanceof SQLXML ) //@PDA jdbc40 { SQLXML xml = (SQLXML)object; String stringVal = xml.getString(); locator_.writeData(0L, converter_.stringToByteArray(stringVal), 0, stringVal.length(), true); } endif */ else { JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); } } finally { savedObject_ = null; } scale_ = (int) locator_.getLength(); }