/**
   * 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;
    }
  }
  /**
   * 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;
    }
  }
  /**
   * 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
    }
  }
Esempio n. 4
0
  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();
  }
Esempio n. 5
0
  // 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);
    }
  }