You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ba...@apache.org on 2005/04/28 21:05:45 UTC

svn commit: r165178 [6/26] - in /incubator/derby/code/trunk: ./ java/client/ java/client/org/ java/client/org/apache/ java/client/org/apache/derby/ java/client/org/apache/derby/client/ java/client/org/apache/derby/client/am/ java/client/org/apache/derby/client/net/ java/client/org/apache/derby/client/resources/ java/client/org/apache/derby/jdbc/ tools/ant/properties/

Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,1153 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.Cursor
+
+   Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.apache.derby.client.am;
+
+// When we calculate column offsets make sure we calculate the correct offsets for double byte charactr5er data
+// length from server is number of chars, not bytes
+// Direct byte-level converters are called directly by this class, cross converters are deferred to the CrossConverters class.
+public abstract class Cursor
+{
+  protected Agent agent_;
+
+  //-----------------------------varchar representations------------------------
+
+  public final static int STRING = 0; 
+  public final static int VARIABLE_STRING = 2;       // uses a 2-byte length indicator
+  public final static int VARIABLE_SHORT_STRING = 1; // aka Pascal L; uses a 1-byte length indicator
+  public final static int NULL_TERMINATED_STRING = 3;
+
+  public final static int BYTES = 4; 
+  public final static int VARIABLE_BYTES = 5;
+  public final static int VARIABLE_SHORT_BYTES = 6;
+  public final static int NULL_TERMINATED_BYTES = 7;
+
+  public final static int SBCS_CLOB = 8;
+  public final static int MBCS_CLOB = 9;
+  public final static int DBCS_CLOB = 10;
+  //-----------------------------internal state---------------------------------
+
+  //-------------Structures for holding and scrolling the data -----------------
+  public byte[] dataBuffer_;
+  public java.io.ByteArrayOutputStream dataBufferStream_;
+  public int position_; // This is the read head
+  public int lastValidBytePosition_;
+  public boolean hasLobs_; // is there at least one LOB column?
+
+  // Current row positioning
+  protected int currentRowPosition_;
+  private int nextRowPosition_;
+  // Let's new up a 2-dimensional array based on fetch-size and reuse so that
+  protected int[] columnDataPosition_; 
+
+  // This is the actual, computed lengths of varchar fields, not the max length from query descriptor or DA
+  protected int[] columnDataComputedLength_;
+  // populate this for
+
+  // All the data is in the buffers, but user may not have necessarily stepped to the last row yet.
+  // This flag indicates that the server has returned all the rows, and is positioned
+  // after last, for both scrollable and forward-only cursors.
+  // For singleton cursors, this memeber will be set to true as soon as next is called.
+  public boolean allRowsReceivedFromServer_;
+
+  // Total number of rows read so far.
+  // This should never exceed this.statement.maxRows
+  int rowsRead_;
+
+  // Maximum column size limit in bytes.
+  int maxFieldSize_ = 0;
+
+  // Row positioning for all cached rows
+  // For scrollable result sets, these lists hold the offsets into the cached rowset buffer for each row of data.
+  protected java.util.ArrayList columnDataPositionCache_ = new java.util.ArrayList();
+  protected java.util.ArrayList columnDataLengthCache_ = new java.util.ArrayList();
+  protected java.util.ArrayList columnDataIsNullCache_ = new java.util.ArrayList();
+  public java.util.ArrayList isUpdateDeleteHoleCache_ = new java.util.ArrayList();
+  public boolean isUpdateDeleteHole_;
+  final static public java.lang.Boolean ROW_IS_NULL = new Boolean (true);
+  final static public java.lang.Boolean ROW_IS_NOT_NULL = new Boolean (false);
+
+  java.sql.Date recyclableDate_ = null;
+  java.sql.Time recyclableTime_ = null;
+  java.sql.Timestamp recyclableTimestamp_ = null;
+
+  // For the net, this data comes from the query descriptor.
+
+  public int[] jdbcTypes_;
+  public int columns_;
+  public boolean[] nullable_;
+  public String[] charsetName_;
+  public boolean[] isNull_;
+  public int[] fdocaLength_; // this is the max length for
+
+  //----------------------------------------------------------------------------
+
+  public int [] ccsid_;
+  char[] charBuffer_;
+
+  //---------------------constructors/finalizer---------------------------------
+
+  public Cursor (Agent agent)
+  {
+    agent_ = agent;
+    dataBufferStream_ = new java.io.ByteArrayOutputStream ();
+  }
+
+  public Cursor (Agent agent, byte[] dataBuffer)
+  {
+    this (agent);
+    dataBuffer_ = dataBuffer;
+    allRowsReceivedFromServer_ = false;
+  }
+
+  public void setNumberOfColumns (int numberOfColumns)
+  {
+    columnDataPosition_ = new int[numberOfColumns];
+    columnDataComputedLength_ = new int[numberOfColumns];
+
+    columns_ = numberOfColumns;
+    nullable_ = new boolean[numberOfColumns];
+    charsetName_ = new String[numberOfColumns];
+
+    ccsid_ = new int [numberOfColumns];
+
+    isNull_ = new boolean[numberOfColumns];
+    jdbcTypes_ = new int[numberOfColumns];
+  }
+
+  // Makes the next row the current row.
+  // Returns true if the current row position is a valid row position.
+  public boolean next () throws SqlException
+  {
+    // local variable usd to hold the returned value from calculateColumnOffsetsForRow()
+    boolean rowPositionIsValid = true;
+
+    // reset lob data
+    // clears out Cursor.lobs_ calculated for the current row when cursor is moved.
+    clearLobData_ ();
+
+    // mark the start of a new row.
+    makeNextRowPositionCurrent ();
+
+    // Drive the CNTQRY outside of calculateColumnOffsetsForRow() if the dataBuffer_
+    // contains no data since it has no abilities to handle replies other than
+    // the QRYDTA, i.e. ENDQRYRM when the result set contains no more rows.
+    while (!dataBufferHasUnprocessedData()) {
+      if (allRowsReceivedFromServer_)
+        return false;
+      getMoreData_();
+    }
+
+    // The parameter passed in here is used as an index into the cached rowset for
+    // scrollable cursors, for the arrays to be reused.  It is not used for forward-only
+    // cursors, so just pass in 0.
+    rowPositionIsValid = calculateColumnOffsetsForRow_(0);  // readFetchedRows()
+    markNextRowPosition ();
+    return rowPositionIsValid;
+  }
+
+  //--------------------------reseting cursor state-----------------------------
+
+  public final void setAllRowsReceivedFromServer (boolean b)
+  {
+    allRowsReceivedFromServer_ = b;
+  }
+
+  public final boolean currentRowPositionIsEqualToNextRowPosition ()
+  {
+    return (currentRowPosition_ == nextRowPosition_);
+  }
+
+  // reset the beginning and ending position in the data buffer to 0
+  // reset the currentRowPosition and nextRowPosition to 0
+  // reset lastRowReached and sqlcode100Received to false
+  // clear the column data offsets cache
+  public final void resetDataBuffer ()
+  {
+    position_ = 0;
+    lastValidBytePosition_ = 0;
+    currentRowPosition_ = 0;
+    nextRowPosition_ = 0;
+    allRowsReceivedFromServer_ = false;
+    dataBufferStream_.reset();
+  }
+
+  public final boolean dataBufferHasUnprocessedData ()
+  {
+    return (lastValidBytePosition_ - position_) > 0;
+  }
+
+  protected abstract boolean calculateColumnOffsetsForRow_ (int row) throws SqlException, DisconnectException;
+  protected abstract void clearLobData_();
+  protected abstract void getMoreData_() throws SqlException;
+
+  // Associate a new underlying COM or SQLDA output data buffer for this converter.
+  public final void setBuffer (byte[] dataBuffer)
+  {
+    dataBuffer_ = dataBuffer;
+  }
+
+  public final void setIsUpdataDeleteHole (int row, boolean isRowNull)
+  {
+    isUpdateDeleteHole_ = isRowNull;
+    Boolean nullIndicator = (isUpdateDeleteHole_ == true) ? ROW_IS_NULL : ROW_IS_NOT_NULL;
+    if (isUpdateDeleteHoleCache_.size() == row)
+      isUpdateDeleteHoleCache_.add (nullIndicator);
+    else
+      isUpdateDeleteHoleCache_.set (row, nullIndicator);
+  }
+  //---------------------------cursor positioning-------------------------------
+
+  final int getPosition ()
+  {
+    return position_;
+  }
+
+  final void setPosition (int newPosition)
+  {
+    position_ = newPosition;
+  }
+
+  public final void markCurrentRowPosition ()
+  {
+    currentRowPosition_ = position_;
+  }
+
+  public final void markNextRowPosition ()
+  {
+    nextRowPosition_ = position_;
+  }
+
+  public final void makeNextRowPositionCurrent ()
+  {
+    currentRowPosition_ = nextRowPosition_;
+  }
+
+  final void repositionCursorToCurrentRow ()
+  {
+    position_ = currentRowPosition_;
+  }
+
+  final void repositionCursorToNextRow ()
+  {
+    position_ = nextRowPosition_;
+  }
+
+  public final byte[] getDataBuffer ()
+  {
+    return dataBuffer_;
+  }
+
+  public final int getDataBufferLength()
+  {
+    return dataBuffer_.length;
+  }
+
+  public final int getLastValidBytePosition ()
+  {
+    return lastValidBytePosition_;
+  }
+
+  // This tracks the total number of rows read into the client side buffer for
+  // this result set, irregardless of scrolling.
+  // Per jdbc semantics, this should never exceed statement.maxRows.
+  // This event should be generated in the materialized cursor's implementation
+  // of calculateColumnOffsetsForRow().
+  public final void incrementRowsReadEvent()
+  {
+    rowsRead_++;
+  }
+
+  //------- the following getters are called on known column types -------------
+  // Direct conversions only, cross conversions are handled by another set of getters.
+
+  // Build a Java short from a 2-byte signed binary representation.
+  private final short get_SMALLINT (int column)
+  {
+    return org.apache.derby.client.am.SignedBinary.getShort (dataBuffer_,
+                                                             columnDataPosition_[column-1]);
+  }
+
+  // Build a Java int from a 4-byte signed binary representation.
+  private final int get_INTEGER (int column)
+  {
+    return org.apache.derby.client.am.SignedBinary.getInt (dataBuffer_,
+                                                           columnDataPosition_[column-1]);
+  }
+
+  // Build a Java long from an 8-byte signed binary representation.
+  private final long get_BIGINT (int column)
+  {
+    return org.apache.derby.client.am.SignedBinary.getLong (dataBuffer_,
+                                                            columnDataPosition_[column-1]);
+  }
+
+  // Build a Java float from a 4-byte floating point representation.
+  private final float get_FLOAT (int column)
+  {
+    return org.apache.derby.client.am.FloatingPoint.getFloat (dataBuffer_,
+                                                      columnDataPosition_[column-1]);
+  }
+
+  // Build a Java double from an 8-byte floating point representation.
+  private final double get_DOUBLE (int column)
+  {
+    return org.apache.derby.client.am.FloatingPoint.getDouble (dataBuffer_,
+                                                       columnDataPosition_[column-1]);
+  }
+
+  // Build a java.math.BigDecimal from a fixed point decimal byte representation.
+  private final java.math.BigDecimal get_DECIMAL (int column) throws SqlException
+  {
+    try {
+      return org.apache.derby.client.am.Decimal.getBigDecimal (dataBuffer_,
+                                                       columnDataPosition_[column-1],
+                                                       getColumnPrecision (column-1),
+                                                       getColumnScale (column-1));
+    }
+    catch (java.io.UnsupportedEncodingException e) {
+      throw new SqlException (agent_.logWriter_, e, "Encoding is unsupported for conversion to BigDecimal");
+    }
+  }
+
+
+  // Build a Java double from a fixed point decimal byte representation.
+  private final double getDoubleFromDECIMAL (int column) throws SqlException
+  {
+    try {
+      return org.apache.derby.client.am.Decimal.getDouble (dataBuffer_,
+                                                   columnDataPosition_[column-1],
+                                                   getColumnPrecision (column-1),
+                                                   getColumnScale (column-1));
+    }
+    catch (java.lang.IllegalArgumentException e) {
+      throw new SqlException (agent_.logWriter_, e, "Decimal value is out of range for conversion to double");
+    }
+    catch (java.io.UnsupportedEncodingException e) {
+      throw new SqlException (agent_.logWriter_, e, "Encoding is unsupported for conversion to BigDecimal");
+    }
+  }
+
+  // Build a Java long from a fixed point decimal byte representation.
+  private final long getLongFromDECIMAL (int column) throws SqlException
+  {
+    try {
+      return org.apache.derby.client.am.Decimal.getLong (dataBuffer_,
+                                                 columnDataPosition_[column-1],
+                                                 getColumnPrecision (column-1),
+                                                 getColumnScale (column-1));
+    }
+    catch (java.lang.IllegalArgumentException e) {
+      throw new SqlException (agent_.logWriter_, e, "Decimal value is out of range for conversion to long");
+    }
+    catch (java.io.UnsupportedEncodingException e) {
+      throw new SqlException (agent_.logWriter_, e, "Encoding is unsupported for conversion to BigDecimal");
+    }
+  }
+
+  // Build a Java String from a database VARCHAR or LONGVARCHAR field.
+  //
+  // Depending on the ccsid, length is the number of chars or number of bytes.
+  // For 2-byte character ccsids, length is the number of characters,
+  // for all other cases length is the number of bytes.
+  // The length does not include the null terminator.
+  private final String getVARCHAR (int column) throws SqlException
+  {
+    String tempString = null;
+    try {
+      if(ccsid_[column-1] == 1200)
+        return getStringWithoutConvert (columnDataPosition_[column-1] + 2, columnDataComputedLength_[column-1] - 2 );
+
+      // check for null encoding is needed because the net layer
+      // will no longer throw an exception if the server didn't specify
+      // a mixed or double byte ccsid (ccsid = 0).  this check for null in the
+      // cursor is only required for types which can have mixed or double
+      // byte ccsids.
+      if (charsetName_[column-1] == null)
+        throw new SqlException (agent_.logWriter_,
+          "Required character converter not available for data type.");
+
+      tempString = new String (dataBuffer_,
+			           columnDataPosition_[column-1] + 2,
+			           columnDataComputedLength_[column-1] - 2,
+			           charsetName_[column-1]);
+      return (maxFieldSize_ == 0) ? tempString :
+        tempString.substring(0, java.lang.Math.min (maxFieldSize_, tempString.length()));
+    }
+    catch (java.io.UnsupportedEncodingException e) {
+      throw new SqlException (agent_.logWriter_, e, "unsupported encoding for result set column " + column);
+    }
+  }
+
+  // Build a Java String from a database CHAR field.
+  private final String getCHAR (int column) throws SqlException
+  {
+    String tempString = null;
+    if (ccsid_[column - 1] == 1200)
+      return getStringWithoutConvert(columnDataPosition_[column - 1], columnDataComputedLength_[column - 1]);
+
+    try {
+      // check for null encoding is needed because the net layer
+      // will no longer throw an exception if the server didn't specify
+      // a mixed or double byte ccsid (ccsid = 0).  this check for null in the
+      // cursor is only required for types which can have mixed or double
+      // byte ccsids.
+      if (charsetName_[column-1] == null)
+        throw new SqlException (agent_.logWriter_,
+          "Required character converter not available for data type.");
+
+      tempString = new String (dataBuffer_,
+                               columnDataPosition_[column-1],
+ 		         columnDataComputedLength_[column-1],
+	         charsetName_[column-1]);
+      return (maxFieldSize_ == 0) ? tempString :
+        tempString.substring(0, java.lang.Math.min (maxFieldSize_, tempString.length()));
+    }
+    catch (java.io.UnsupportedEncodingException e) {
+      throw new SqlException (agent_.logWriter_, e, "unsupported encoding for result set column " + column);
+    }
+  }
+
+  // Build a JDBC Date object from the DERBY ISO DATE field.
+  private final java.sql.Date getDATE (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.dateBytesToDate (dataBuffer_,
+                                                                  columnDataPosition_[column-1],
+                                                                  recyclableDate_);
+  }
+
+  // Build a JDBC Time object from the DERBY ISO TIME field.
+  private final java.sql.Time getTIME (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timeBytesToTime (dataBuffer_,
+                                                                  columnDataPosition_[column-1],
+                                                                   recyclableTime_);
+  }
+
+  // Build a JDBC Timestamp object from the DERBY ISO TIMESTAMP field.
+  private final java.sql.Timestamp getTIMESTAMP (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timestampBytesToTimestamp (dataBuffer_,
+                                                                            columnDataPosition_[column-1],
+                                                                            recyclableTimestamp_);
+  }
+
+  // Build a JDBC Timestamp object from the DERBY ISO DATE field.
+  private final java.sql.Timestamp getTimestampFromDATE (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.dateBytesToTimestamp (dataBuffer_,
+                                                                       columnDataPosition_[column-1],
+                                                                       recyclableTimestamp_);
+  }
+
+  // Build a JDBC Timestamp object from the DERBY ISO TIME field.
+  private final java.sql.Timestamp getTimestampFromTIME (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timeBytesToTimestamp (dataBuffer_,
+                                                                       columnDataPosition_[column-1],
+                                                                       recyclableTimestamp_);
+  }
+
+  // Build a JDBC Date object from the DERBY ISO TIMESTAMP field.
+  private final java.sql.Date getDateFromTIMESTAMP (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timestampBytesToDate (dataBuffer_,
+                                                                       columnDataPosition_[column-1],
+                                                                       recyclableDate_);
+  }
+
+  // Build a JDBC Time object from the DERBY ISO TIMESTAMP field.
+  private final java.sql.Time getTimeFromTIMESTAMP (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timestampBytesToTime (dataBuffer_,
+                                                                       columnDataPosition_[column-1],
+                                                                       recyclableTime_);
+  }
+
+ private final String getStringFromDATE (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.dateBytesToDate (
+               dataBuffer_,
+               columnDataPosition_[column-1],
+               recyclableDate_).toString();
+  }
+
+  // Build a string object from the DERBY byte TIME representation.
+  private final String getStringFromTIME (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timeBytesToTime (
+               dataBuffer_,
+               columnDataPosition_[column-1],
+               recyclableTime_).toString();
+  }
+
+  // Build a string object from the DERBY byte TIMESTAMP representation.
+  private final String getStringFromTIMESTAMP (int column) throws SqlException
+  {
+    return org.apache.derby.client.am.DateTime.timestampBytesToTimestamp (
+               dataBuffer_,
+               columnDataPosition_[column-1],
+               recyclableTimestamp_).toString();
+  }
+
+  // Extract bytes from a database java.sql.Types.BINARY field.
+  // This is the DERBY type CHAR(n) FOR BIT DATA.
+  private final byte[] get_CHAR_FOR_BIT_DATA (int column) throws SqlException
+  {
+    // There is no limit to the size of a column if maxFieldSize is zero.
+    // Otherwise, use the smaller of maxFieldSize and the actual column length.
+    int columnLength = (maxFieldSize_ == 0) ? columnDataComputedLength_[column-1] :
+      java.lang.Math.min (maxFieldSize_, columnDataComputedLength_[column-1]);
+
+    byte[] bytes = new byte[columnLength];
+    System.arraycopy (dataBuffer_, columnDataPosition_[column-1], bytes, 0, columnLength);
+    return bytes;
+  }
+
+  // Extract bytes from a database java.sql.Types.VARBINARY or LONGVARBINARY field.
+  // This includes the DERBY types:
+  //   VARCHAR(n) FOR BIT DATA
+  //   LONG VARCHAR(n) FOR BIT DATA
+  private final byte[] get_VARCHAR_FOR_BIT_DATA (int column) throws SqlException
+  {
+    byte[] bytes;
+    int columnLength = 0;
+    columnLength = (maxFieldSize_ == 0) ? columnDataComputedLength_[column-1]-2 :
+      java.lang.Math.min (maxFieldSize_, columnDataComputedLength_[column-1]-2);
+    bytes = new byte[columnLength];
+    System.arraycopy (dataBuffer_, columnDataPosition_[column-1] + 2, bytes, 0, bytes.length);
+    return bytes;
+  }
+
+  abstract public Blob getBlobColumn_ (int column, Agent agent) throws SqlException;
+  abstract public Clob getClobColumn_ (int column, Agent agent) throws SqlException;
+
+  // get the raw clob bytes, without translation.  dataOffset must be int[1]
+  abstract public byte[] getClobBytes_ (int column, int[] dataOffset /*output*/) throws SqlException;
+
+  //------- the following getters perform any necessary cross-conversion _------
+
+  final boolean getBoolean (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.SMALLINT:
+      return agent_.crossConverters_.getBooleanFromShort (get_SMALLINT (column));
+    case java.sql.Types.INTEGER:
+      return agent_.crossConverters_.getBooleanFromInt (get_INTEGER (column));
+    case java.sql.Types.BIGINT:
+      return agent_.crossConverters_.getBooleanFromLong (get_BIGINT (column));
+    case java.sql.Types.REAL:
+      return agent_.crossConverters_.getBooleanFromFloat (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return agent_.crossConverters_.getBooleanFromDouble (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return agent_.crossConverters_.getBooleanFromLong (getLongFromDECIMAL (column));
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getBooleanFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getBooleanFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final byte getByte (int column) throws SqlException
+  {
+    // This needs to be changed to use jdbcTypes[] 
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.SMALLINT:
+      return agent_.crossConverters_.getByteFromShort (get_SMALLINT (column));
+    case java.sql.Types.INTEGER:
+      return agent_.crossConverters_.getByteFromInt (get_INTEGER (column));
+    case java.sql.Types.BIGINT:
+      return agent_.crossConverters_.getByteFromLong (get_BIGINT (column));
+    case java.sql.Types.REAL:
+      return agent_.crossConverters_.getByteFromFloat (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return agent_.crossConverters_.getByteFromDouble (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return agent_.crossConverters_.getByteFromLong (getLongFromDECIMAL (column));
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getByteFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getByteFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final short getShort (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.SMALLINT:
+      return get_SMALLINT (column);
+    case java.sql.Types.INTEGER:
+      return agent_.crossConverters_.getShortFromInt (get_INTEGER (column));
+    case java.sql.Types.BIGINT:
+      return agent_.crossConverters_.getShortFromLong (get_BIGINT (column));
+    case java.sql.Types.REAL:
+      return agent_.crossConverters_.getShortFromFloat (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return agent_.crossConverters_.getShortFromDouble (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return agent_.crossConverters_.getShortFromLong (getLongFromDECIMAL (column));
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getShortFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getShortFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final int getInt (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.SMALLINT:
+      return (int) get_SMALLINT (column);
+    case java.sql.Types.INTEGER:
+      return get_INTEGER (column);
+    case java.sql.Types.BIGINT:
+      return agent_.crossConverters_.getIntFromLong (get_BIGINT (column));
+    case java.sql.Types.REAL:
+      return agent_.crossConverters_.getIntFromFloat (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return agent_.crossConverters_.getIntFromDouble (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return agent_.crossConverters_.getIntFromLong (getLongFromDECIMAL (column));
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getIntFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getIntFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final long getLong (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.SMALLINT:
+      return (long) get_SMALLINT (column);
+    case java.sql.Types.INTEGER:
+      return (long) get_INTEGER (column);
+    case java.sql.Types.BIGINT:
+      return get_BIGINT (column);
+    case java.sql.Types.REAL:
+      return agent_.crossConverters_.getLongFromFloat (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return agent_.crossConverters_.getLongFromDouble (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return getLongFromDECIMAL (column);
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getLongFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getLongFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final float getFloat (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.REAL:
+      return get_FLOAT (column);
+    case java.sql.Types.DOUBLE:
+      return agent_.crossConverters_.getFloatFromDouble (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return agent_.crossConverters_.getFloatFromDouble (getDoubleFromDECIMAL (column));
+    case java.sql.Types.SMALLINT:
+      return (float) get_SMALLINT (column);
+    case java.sql.Types.INTEGER:
+      return (float) get_INTEGER (column);
+    case java.sql.Types.BIGINT:
+      return (float) get_BIGINT (column);
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getFloatFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getFloatFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final double getDouble (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.REAL:
+      double d = (double) get_FLOAT (column);
+      return d;
+      //return (double) get_FLOAT (column);
+    case java.sql.Types.DOUBLE:
+      return get_DOUBLE (column);
+    case java.sql.Types.DECIMAL:
+      // For performance we don't materialize the BigDecimal, but convert directly from decimal bytes to a long.
+      return getDoubleFromDECIMAL (column);
+    case java.sql.Types.SMALLINT:
+      return (double) get_SMALLINT (column);
+    case java.sql.Types.INTEGER:
+      return (double) get_INTEGER (column);
+    case java.sql.Types.BIGINT:
+      return (double) get_BIGINT (column);
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getDoubleFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getDoubleFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final java.math.BigDecimal getBigDecimal (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.DECIMAL:
+      return get_DECIMAL (column);
+    case java.sql.Types.REAL:
+      // Can't use the following commented out line because it changes precision of the result.
+      //return new java.math.BigDecimal (get_FLOAT (column));
+      float f = get_FLOAT (column);
+      return new java.math.BigDecimal (String.valueOf(f));
+    case java.sql.Types.DOUBLE:
+      // Can't use the following commented out line because it changes precision of the result.
+      return new java.math.BigDecimal (String.valueOf (get_DOUBLE (column)));
+    case java.sql.Types.SMALLINT:
+      return java.math.BigDecimal.valueOf (get_SMALLINT (column));
+    case java.sql.Types.INTEGER:
+      return java.math.BigDecimal.valueOf (get_INTEGER (column));
+    case java.sql.Types.BIGINT:
+      return java.math.BigDecimal.valueOf (get_BIGINT (column));
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getBigDecimalFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getBigDecimalFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final java.sql.Date getDate (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.DATE:
+      return getDATE (column);
+    case java.sql.Types.TIMESTAMP:
+      return getDateFromTIMESTAMP (column);
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getDateFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getDateFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final java.sql.Time getTime (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.TIME:
+      return getTIME (column);
+    case java.sql.Types.TIMESTAMP:
+      return getTimeFromTIMESTAMP (column);
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getTimeFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getTimeFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final java.sql.Timestamp getTimestamp (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.TIMESTAMP:
+      return getTIMESTAMP (column);
+    case java.sql.Types.DATE:
+      return getTimestampFromDATE (column);
+    case java.sql.Types.TIME:
+      return getTimestampFromTIME (column);
+    case java.sql.Types.CHAR:
+      return agent_.crossConverters_.getTimestampFromString (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return agent_.crossConverters_.getTimestampFromString (getVARCHAR (column));
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final String getString (int column) throws SqlException
+  {
+    String tempString = null;
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.CHAR:
+      return getCHAR (column);
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return getVARCHAR (column);
+
+    case java.sql.Types.SMALLINT:
+      return String.valueOf (get_SMALLINT (column));
+    case java.sql.Types.INTEGER:
+      return String.valueOf (get_INTEGER (column));
+    case java.sql.Types.BIGINT:
+      return String.valueOf (get_BIGINT (column));
+    case java.sql.Types.REAL:
+      return String.valueOf (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return String.valueOf (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      // We could get better performance here if we didn't materialize the BigDecimal,
+      // but converted directly from decimal bytes to a string.
+      return String.valueOf (get_DECIMAL (column));
+    case java.sql.Types.DATE:
+      return getStringFromDATE (column);
+    case java.sql.Types.TIME:
+      return getStringFromTIME (column);
+    case java.sql.Types.TIMESTAMP:
+      return getStringFromTIMESTAMP (column);
+    case Types.BINARY:
+      tempString =
+        agent_.crossConverters_.getStringFromBytes (get_CHAR_FOR_BIT_DATA (column));
+      return (maxFieldSize_ == 0) ? tempString :
+        tempString.substring(0, java.lang.Math.min (maxFieldSize_, tempString.length()));
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      tempString =
+        agent_.crossConverters_.getStringFromBytes (get_VARCHAR_FOR_BIT_DATA (column));
+      return (maxFieldSize_ == 0) ? tempString :
+        tempString.substring(0, java.lang.Math.min (maxFieldSize_, tempString.length()));
+    case java.sql.Types.BLOB:
+      Blob b = (Blob) getBlobColumn_ (column, agent_);
+      return agent_.crossConverters_.getStringFromBytes (b.getBytes(1, (int) b.length()));
+    case java.sql.Types.CLOB:
+      Clob c = getClobColumn_ (column, agent_);
+      return c.getSubString (1, (int) c.length());
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  final byte[] getBytes (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.BINARY:
+      return get_CHAR_FOR_BIT_DATA (column);
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      return get_VARCHAR_FOR_BIT_DATA (column);
+    case java.sql.Types.BLOB:
+      Blob b = (Blob) getBlobColumn_ (column, agent_);
+      return b.getBytes (1, (int) b.length()); 
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.io.InputStream getBinaryStream (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.BINARY:
+      return new java.io.ByteArrayInputStream (get_CHAR_FOR_BIT_DATA (column));
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      return new java.io.ByteArrayInputStream (get_VARCHAR_FOR_BIT_DATA (column));
+    case java.sql.Types.BLOB:
+      Blob b = (Blob) getBlobColumn_ (column, agent_);
+      return b.getBinaryStream();
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.io.InputStream getAsciiStream (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.CLOB:
+      Clob c = getClobColumn_ (column, agent_);
+      return c.getAsciiStream();
+    case java.sql.Types.CHAR:
+      try {
+        return new java.io.ByteArrayInputStream (getCHAR(column).getBytes("US-ASCII"));
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, e.getMessage());
+      }
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      try {
+        return new java.io.ByteArrayInputStream (getVARCHAR(column).getBytes("US-ASCII"));
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, e.getMessage());
+      }
+    case java.sql.Types.BINARY:
+      return new java.io.ByteArrayInputStream (get_CHAR_FOR_BIT_DATA (column));
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      return new java.io.ByteArrayInputStream (get_VARCHAR_FOR_BIT_DATA (column));
+    case java.sql.Types.BLOB:
+      Blob b = (Blob) getBlobColumn_ (column, agent_);
+      return b.getBinaryStream();
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.io.InputStream getUnicodeStream (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.CLOB: {
+      Clob c = getClobColumn_ (column, agent_);
+      String s = c.getSubString (1L, (int) c.length());
+      try {
+        return new java.io.ByteArrayInputStream (s.getBytes ("UTF-8"));
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, e.getMessage());
+      }
+    }
+    case java.sql.Types.CHAR: {
+      try {
+        return new java.io.ByteArrayInputStream (getCHAR (column).getBytes ("UTF-8"));
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, e.getMessage());
+      }
+    }
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      try {
+        return new java.io.ByteArrayInputStream (getVARCHAR(column).getBytes ("UTF-8"));
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, e.getMessage());
+      }
+    case java.sql.Types.BINARY:
+      return new java.io.ByteArrayInputStream (get_CHAR_FOR_BIT_DATA (column));
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      return new java.io.ByteArrayInputStream (get_VARCHAR_FOR_BIT_DATA (column));
+    case java.sql.Types.BLOB:
+      Blob b = (Blob) getBlobColumn_ (column, agent_);
+      return b.getBinaryStream();
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.io.Reader getCharacterStream (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.CLOB:
+      Clob c = getClobColumn_ (column, agent_);
+      return c.getCharacterStream();
+    case java.sql.Types.CHAR:
+      return new java.io.StringReader (getCHAR (column));
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return new java.io.StringReader (getVARCHAR (column));
+    case java.sql.Types.BINARY:
+      try {
+        return new java.io.InputStreamReader (new java.io.ByteArrayInputStream (get_CHAR_FOR_BIT_DATA (column)), "UTF-16BE");
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, "UnsupportedEncodingException: " + e.getMessage());
+      }
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      try {
+        return new java.io.InputStreamReader (new java.io.ByteArrayInputStream (get_VARCHAR_FOR_BIT_DATA (column)), "UTF-16BE");
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, "UnsupportedEncodingException: " + e.getMessage());
+      }
+    case java.sql.Types.BLOB:
+      try {
+        Blob b = (Blob) getBlobColumn_ (column, agent_);
+        return new java.io.InputStreamReader (b.getBinaryStream(), "UTF-16BE");
+      }
+      catch (java.io.UnsupportedEncodingException e) {
+        throw new SqlException (agent_.logWriter_, "UnsupportedEncodingException: " + e.getMessage());
+      }
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.sql.Blob getBlob (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case Types.BLOB:
+      return getBlobColumn_ (column, agent_);
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.sql.Clob getClob (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case Types.CLOB:
+      return getClobColumn_ (column, agent_);
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final java.sql.Array getArray (int column) throws SqlException
+  {
+    throw new SqlException (agent_.logWriter_, "not yet implemented");
+  }
+
+  public final java.sql.Ref getRef (int column) throws SqlException
+  {
+    throw new SqlException (agent_.logWriter_, "not yet implemented");
+  }
+
+  public final Object getObject (int column) throws SqlException
+  {
+    switch (jdbcTypes_[column-1]) {
+    case java.sql.Types.SMALLINT:
+      return new Integer (get_SMALLINT (column)); // See Table 4 in JDBC 1 spec (pg. 932 in jdbc book)
+    case java.sql.Types.INTEGER:
+      return new Integer (get_INTEGER (column));
+    case java.sql.Types.BIGINT:
+      return new Long (get_BIGINT (column));
+    case java.sql.Types.REAL:
+      return new Float (get_FLOAT (column));
+    case java.sql.Types.DOUBLE:
+      return new Double (get_DOUBLE (column));
+    case java.sql.Types.DECIMAL:
+      return get_DECIMAL (column);
+    case java.sql.Types.DATE:
+      return getDATE (column);
+    case java.sql.Types.TIME:
+      return getTIME (column);
+    case java.sql.Types.TIMESTAMP:
+      return getTIMESTAMP (column);
+    case java.sql.Types.CHAR:
+      return getCHAR (column);
+    case java.sql.Types.VARCHAR:
+    case java.sql.Types.LONGVARCHAR:
+      return getVARCHAR (column);
+    case Types.BINARY:
+      return get_CHAR_FOR_BIT_DATA (column);
+    case java.sql.Types.VARBINARY:
+    case java.sql.Types.LONGVARBINARY:
+      return get_VARCHAR_FOR_BIT_DATA (column);
+    case java.sql.Types.BLOB:
+      return getBlobColumn_ (column, agent_);
+    case java.sql.Types.CLOB:
+      return getClobColumn_ (column, agent_);
+    default:
+      throw new ColumnTypeConversionException (agent_.logWriter_);
+    }
+  }
+
+  public final void allocateCharBuffer ()
+  {
+    // compute the maximum char length
+    int maxCharLength = 0;
+    for (int i=0; i<columns_; i++) {
+      switch (jdbcTypes_[i]) {
+      case Types.CHAR:
+      case Types.VARCHAR:
+      case Types.LONGVARCHAR:
+        if (fdocaLength_[i] > maxCharLength) maxCharLength = fdocaLength_[i];
+      }
+    }
+
+    // allocate char buffer to accomodate largest result column
+    charBuffer_ = new char[maxCharLength]; 
+  }
+
+  private final String getStringWithoutConvert (int position, int actualLength) throws SqlException
+  {
+    int start = position;
+    int end = position + actualLength;
+
+    int charCount = 0;
+      while (start < end)
+      {
+         charBuffer_[charCount++] = (char) (((dataBuffer_[start]&0xff)<<8) | (dataBuffer_[start+1]&0xff));
+         start += 2;
+    }
+
+    return new String(charBuffer_, 0, charCount);
+  }
+
+  public void nullDataForGC ()
+  {
+    dataBuffer_ = null;
+    dataBufferStream_ = null;
+    columnDataPosition_ = null;
+    columnDataComputedLength_ = null;
+    columnDataPositionCache_ = null;
+    columnDataLengthCache_ = null;
+    columnDataIsNullCache_ = null;
+    jdbcTypes_ = null;
+    nullable_ = null;
+    charsetName_ = null;
+    this.ccsid_ = null;
+    isUpdateDeleteHoleCache_ = null;
+    isNull_ = null;
+    fdocaLength_ = null;
+    charBuffer_ = null;
+  }
+
+  private final int getColumnPrecision (int column)
+  {
+    return ((fdocaLength_[column] >> 8) & 0xff);
+  }
+
+  private final int getColumnScale (int column)
+  {
+    return (fdocaLength_[column] & 0xff);
+  }
+
+  // Only used by Sqlca.getMessage() when using a locale encoding
+  // to convert errror message text instead of relying on server encoding as usual.
+  final byte[] getBytesFromVARCHAR (int column) throws SqlException
+  {
+    byte[] bytes;
+    bytes = new byte[columnDataComputedLength_[column-1]-2];
+    System.arraycopy (dataBuffer_, columnDataPosition_[column-1]+2, bytes, 0, bytes.length);
+    return bytes;
+  }
+}

Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java
------------------------------------------------------------------------------
    svn:eol-style = native