Logo Search packages:      
Sourcecode: mysql-connector-java version File versions  Download package

ResultSetImpl.java

/*
 Copyright (C) 2002-2007 MySQL AB

 This program is free software; you can redistribute it and/or modify
 it under the terms of version 2 of the GNU General Public License as
 published by the Free Software Foundation.

 There are special exceptions to the terms and conditions of the GPL
 as it is applied to this software. View the full text of the
 exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
 software distribution.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



 */
package com.mysql.jdbc;

import com.mysql.jdbc.PreparedStatement.ParseInfo;
import com.mysql.jdbc.exceptions.NotYetImplementedException;
import com.mysql.jdbc.profiler.ProfileEventSink;
import com.mysql.jdbc.profiler.ProfilerEvent;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;

import java.net.MalformedURLException;
import java.net.URL;

import java.sql.Array;
import java.sql.DataTruncation;
import java.sql.Date;
import java.sql.Ref;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.TreeMap;

/**
 * A ResultSet provides access to a table of data generated by executing a
 * Statement. The table rows are retrieved in sequence. Within a row its column
 * values can be accessed in any order.
 * 
 * <P>
 * A ResultSet maintains a cursor pointing to its current row of data. Initially
 * the cursor is positioned before the first row. The 'next' method moves the
 * cursor to the next row.
 * </p>
 * 
 * <P>
 * The getXXX methods retrieve column values for the current row. You can
 * retrieve values either using the index number of the column, or by using the
 * name of the column. In general using the column index will be more efficient.
 * Columns are numbered from 1.
 * </p>
 * 
 * <P>
 * For maximum portability, ResultSet columns within each row should be read in
 * left-to-right order and each column should be read only once.
 * </p>
 * 
 * <P>
 * For the getXXX methods, the JDBC driver attempts to convert the underlying
 * data to the specified Java type and returns a suitable Java value. See the
 * JDBC specification for allowable mappings from SQL types to Java types with
 * the ResultSet getXXX methods.
 * </p>
 * 
 * <P>
 * Column names used as input to getXXX methods are case insenstive. When
 * performing a getXXX using a column name, if several columns have the same
 * name, then the value of the first matching column will be returned. The
 * column name option is designed to be used when column names are used in the
 * SQL Query. For columns that are NOT explicitly named in the query, it is best
 * to use column numbers. If column names were used there is no way for the
 * programmer to guarentee that they actually refer to the intended columns.
 * </p>
 * 
 * <P>
 * A ResultSet is automatically closed by the Statement that generated it when
 * that Statement is closed, re-executed, or is used to retrieve the next result
 * from a sequence of multiple results.
 * </p>
 * 
 * <P>
 * The number, types and properties of a ResultSet's columns are provided by the
 * ResultSetMetaData object returned by the getMetaData method.
 * </p>
 * 
 * @author Mark Matthews
 * @version $Id: ResultSetImpl.java 6588 2007-09-15 21:01:29Z mmatthews $
 * 
 * @see ResultSetMetaData
 * @see java.sql.ResultSet
 */
00123 public class ResultSetImpl implements ResultSetInternalMethods {

      private static final Constructor JDBC_4_RS_4_ARG_CTOR;
      private static final Constructor JDBC_4_RS_6_ARG_CTOR;;
      private static final Constructor JDBC_4_UPD_RS_6_ARG_CTOR;
      
      static {
            if (Util.isJdbc4()) {
                  try {
                        JDBC_4_RS_4_ARG_CTOR = Class.forName(
                                    "com.mysql.jdbc.JDBC4ResultSet").getConstructor(
                                    new Class[] { Long.TYPE, Long.TYPE,
                                                ConnectionImpl.class,
                                                com.mysql.jdbc.StatementImpl.class });
                        JDBC_4_RS_6_ARG_CTOR = Class.forName(
                                    "com.mysql.jdbc.JDBC4ResultSet").getConstructor(
                                    new Class[] { String.class, Field[].class,
                                                RowData.class, 
                                                ConnectionImpl.class,
                                                com.mysql.jdbc.StatementImpl.class });
                        JDBC_4_UPD_RS_6_ARG_CTOR = Class.forName(
                                    "com.mysql.jdbc.JDBC4UpdatableResultSet")
                                    .getConstructor(
                                                new Class[] { String.class, Field[].class,
                                                            RowData.class,
                                                            ConnectionImpl.class,
                                                            com.mysql.jdbc.StatementImpl.class });
                  } catch (SecurityException e) {
                        throw new RuntimeException(e);
                  } catch (NoSuchMethodException e) {
                        throw new RuntimeException(e);
                  } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                  }
            } else {
                  JDBC_4_RS_4_ARG_CTOR = null;
                  JDBC_4_RS_6_ARG_CTOR = null;
                  JDBC_4_UPD_RS_6_ARG_CTOR = null;
            }
      }
      
      /**
       * Epsillon between Float.MIN_VALUE and the double representation of said value.
       */
00167     protected static final double MIN_DIFF_PREC = Float.parseFloat(Float.toString(Float.MIN_VALUE))
        - Double.parseDouble(Float.toString(Float.MIN_VALUE));
    
    /**
       * Epsillon between Float.MAX_VALUE and the double representation of said value.
       */
00173     protected static final double MAX_DIFF_PREC = Float.parseFloat(Float.toString(Float.MAX_VALUE))
        - Double.parseDouble(Float.toString(Float.MAX_VALUE));
    
      /** Counter used to generate IDs for profiling. */
00177       protected static int resultCounter = 1;

      /**
       * Converts the given value as a java long, to an 'unsigned' long, using the
       * java.math.BigInteger class.
       */
00183       protected static BigInteger convertLongToUlong(long longVal) {
            byte[] asBytes = new byte[8];
            asBytes[7] = (byte) (longVal & 0xff);
            asBytes[6] = (byte) (longVal >>> 8);
            asBytes[5] = (byte) (longVal >>> 16);
            asBytes[4] = (byte) (longVal >>> 24);
            asBytes[3] = (byte) (longVal >>> 32);
            asBytes[2] = (byte) (longVal >>> 40);
            asBytes[1] = (byte) (longVal >>> 48);
            asBytes[0] = (byte) (longVal >>> 56);

            return new BigInteger(1, asBytes);
      }

      /** The catalog that was in use when we were created */
00198       protected String catalog = null;

      /** Map column names (and all of their permutations) to column indices */
00201       protected Map columnNameToIndex = null;

      /** Keep track of columns accessed */
00204       protected boolean[] columnUsed = null;

      /** The Connection instance that created us */
00207       protected ConnectionImpl connection; // The connection that
                                                           // created us

      protected long connectionId = 0;
      
      /** The current row #, -1 == before start of result set */
00213       protected int currentRow = -1; // Cursor to current row;

      TimeZone defaultTimeZone;

      /** Are we in the middle of doing updates to the current row? */
00218       protected boolean doingUpdates = false;

      protected ProfileEventSink eventSink = null;

      Calendar fastDateCal = null;

      /** The direction to fetch rows (always FETCH_FORWARD) */
00225       protected int fetchDirection = FETCH_FORWARD;

      /** The number of rows to fetch in one go... */
00228       protected int fetchSize = 0;

      /** The fields for this result set */
00231       protected Field[] fields; // The fields

      /**
       * First character of the query that created this result set...Used to
       * determine whether or not to parse server info messages in certain
       * circumstances.
       */
00238       protected char firstCharOfQuery;

      /** Map of fully-specified column names to column indices */
00241       protected Map fullColumnNameToIndex = null;

      protected boolean hasBuiltIndexMapping = false;

      /**
       * Is the data stored as strings (default) or natively (which is the case
       * with results from PrepStmts)
       */
00249       protected boolean isBinaryEncoded = false;

      /** Has this result set been closed? */
00252       protected boolean isClosed = false;

      protected ResultSetInternalMethods nextResultSet = null;

      /** Are we on the insert row? */
00257       protected boolean onInsertRow = false;

      /** The statement that created us */
00260       protected com.mysql.jdbc.StatementImpl owningStatement;

      /**
       * StackTrace generated where ResultSet was created... used when profiling
       */
00265       protected Throwable pointOfOrigin;

      /** Are we tracking items for profileSql? */
00268       protected boolean profileSql = false;

      /**
       * Do we actually contain rows, or just information about
       * UPDATE/INSERT/DELETE?
       */
00274       protected boolean reallyResult = false;

      /** The id (used when profiling) to identify us */
00277       protected int resultId;

      /** Are we read-only or updatable? */
00280       protected int resultSetConcurrency = 0;

      /** Are we scroll-sensitive/insensitive? */
00283       protected int resultSetType = 0;

      /** The actual rows */
00286       protected RowData rowData; // The results

      /**
       * Any info message from the server that was created while generating this
       * result set (if 'info parsing' is enabled for the connection).
       */
00292       protected String serverInfo = null;

      PreparedStatement statementUsedForFetchingRows;

      /** Pointer to current row data */
00297       protected ResultSetRow thisRow = null; // Values for current row

      // These are longs for
      // recent versions of the MySQL server.
      //
      // They get reduced to ints via the JDBC API,
      // but can be retrieved through a MySQLStatement
      // in their entirety.
      //

      /** How many rows were affected by UPDATE/INSERT/DELETE? */
00308       protected long updateCount;

      /** Value generated for AUTO_INCREMENT columns */
00311       protected long updateId = -1;

      private boolean useStrictFloatingPoint = false;

      protected boolean useUsageAdvisor = false;

      /** The warning chain */
00318       protected java.sql.SQLWarning warningChain = null;

      /** Did the previous value retrieval find a NULL? */
00321       protected boolean wasNullFlag = false;

      protected java.sql.Statement wrapperStatement;

      protected boolean retainOwningStatement;

      protected Calendar gmtCalendar = null;

      protected boolean useFastDateParsing = false;

      private boolean padCharsWithSpace = false;

      private boolean jdbcCompliantTruncationForReads;
      
      private boolean useFastIntParsing = true;
      
      protected final static char[] EMPTY_SPACE = new char[255];
      
      static {
            for (int i = 0; i < EMPTY_SPACE.length; i++) {
                  EMPTY_SPACE[i] = ' ';
            }
      }
      
      protected static ResultSetImpl getInstance(long updateCount, long updateID,
                  ConnectionImpl conn, StatementImpl creatorStmt) throws SQLException {
            if (!Util.isJdbc4()) {
                  return new ResultSetImpl(updateCount, updateID, conn, creatorStmt);
            }

            return (ResultSetImpl) Util.handleNewInstance(JDBC_4_RS_4_ARG_CTOR,
                        new Object[] { Constants.longValueOf(updateCount), Constants.longValueOf(updateID), conn,
                                    creatorStmt });
      }

      /**
       * Creates a result set instance that represents a query result -- We need
       * to provide factory-style methods so we can support both JDBC3 (and older)
       * and JDBC4 runtimes, otherwise the class verifier complains when it tries
       * to load JDBC4-only interface classes that are present in JDBC4 method
       * signatures.
       */

00364       protected static ResultSetImpl getInstance(String catalog, Field[] fields,
                  RowData tuples, ConnectionImpl conn, StatementImpl creatorStmt,
                  boolean isUpdatable) throws SQLException {
            if (!Util.isJdbc4()) {
                  if (!isUpdatable) {
                        return new ResultSetImpl(catalog, fields, tuples, conn, creatorStmt);
                  }

                  return new UpdatableResultSet(catalog, fields, tuples, conn,
                              creatorStmt);
            }

            if (!isUpdatable) {
                  return (ResultSetImpl) Util
                              .handleNewInstance(JDBC_4_RS_6_ARG_CTOR, new Object[] {
                                          catalog, fields, tuples, conn, creatorStmt });
            }

            return (ResultSetImpl) Util.handleNewInstance(JDBC_4_UPD_RS_6_ARG_CTOR,
                        new Object[] { catalog, fields, tuples, conn, creatorStmt });
      }

      /**
       * Create a result set for an executeUpdate statement.
       * 
       * @param updateCount
       *            the number of rows affected by the update
       * @param updateID
       *            the autoincrement value (if any)
       * @param conn
       *            DOCUMENT ME!
       * @param creatorStmt
       *            DOCUMENT ME!
       */
00398       public ResultSetImpl(long updateCount, long updateID, ConnectionImpl conn,
                  StatementImpl creatorStmt) {
            this.updateCount = updateCount;
            this.updateId = updateID;
            this.reallyResult = false;
            this.fields = new Field[0];

            this.connection = conn;
            this.owningStatement = creatorStmt;
            
            this.retainOwningStatement = false;
            
            if (this.connection != null) {
                  this.retainOwningStatement = 
                        this.connection.getRetainStatementAfterResultSetClose();
                  
                  this.connectionId = this.connection.getId();
            }
      }

      /**
       * Creates a new ResultSet object.
       * 
       * @param catalog
       *            the database in use when we were created
       * @param fields
       *            an array of Field objects (basically, the ResultSet MetaData)
       * @param tuples
       *            actual row data
       * @param conn
       *            the Connection that created us.
       * @param creatorStmt
       *            DOCUMENT ME!
       * 
       * @throws SQLException
       *             if an error occurs
       */
00435       public ResultSetImpl(String catalog, Field[] fields, RowData tuples,
                  ConnectionImpl conn, StatementImpl creatorStmt) throws SQLException {
            this.connection = conn;

            this.retainOwningStatement = false;
            
            if (this.connection != null) {
                  this.useStrictFloatingPoint = this.connection
                              .getStrictFloatingPoint();
                  this.setDefaultTimeZone(this.connection.getDefaultTimeZone());
                  this.connectionId = this.connection.getId();
                  this.useFastDateParsing = this.connection.getUseFastDateParsing();
                  this.profileSql = this.connection.getProfileSql();
                  this.retainOwningStatement = 
                        this.connection.getRetainStatementAfterResultSetClose();
                  this.jdbcCompliantTruncationForReads = this.connection.getJdbcCompliantTruncationForReads();
                  this.useFastIntParsing = this.connection.getUseFastIntParsing();
            }

            this.owningStatement = creatorStmt;

            this.catalog = catalog;

            this.fields = fields;
            this.rowData = tuples;
            this.updateCount = this.rowData.size();

            if (Driver.DEBUG) {
                  System.out.println(Messages.getString("ResultSet.Retrieved__1")
                              + this.updateCount + " rows"); //$NON-NLS-1$
            }

            this.reallyResult = true;

            // Check for no results
            if (this.rowData.size() > 0) {
                  if (this.updateCount == 1) {
                        if (this.thisRow == null) {
                              this.rowData.close(); // empty result set
                              this.updateCount = -1;
                        }
                  }
            } else {
                  this.thisRow = null;
            }

            this.rowData.setOwner(this);

            if (this.fields != null) {
                  initializeWithMetadata();
            } // else called by Connection.initializeResultsMetadataFromCache() when cached
      }

      public void initializeWithMetadata() throws SQLException {
            this.rowData.setMetadata(this.fields);
            
            if (this.profileSql || this.connection.getUseUsageAdvisor()) {
                  this.columnUsed = new boolean[this.fields.length];
                  this.pointOfOrigin = new Throwable();
                  this.resultId = resultCounter++;
                  this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
                  this.eventSink = ProfileEventSink.getInstance(this.connection);
            }

            if (this.connection.getGatherPerformanceMetrics()) {
                  this.connection.incrementNumberOfResultSetsCreated();

                  Map tableNamesMap = new HashMap();

                  for (int i = 0; i < this.fields.length; i++) {
                        Field f = this.fields[i];

                        String tableName = f.getOriginalTableName();

                        if (tableName == null) {
                              tableName = f.getTableName();
                        }

                        if (tableName != null) {
                              if (this.connection.lowerCaseTableNames()) {
                                    tableName = tableName.toLowerCase(); // on windows, table
                                    // names are not case-sens.
                              }

                              tableNamesMap.put(tableName, null);
                        }
                  }

                  this.connection.reportNumberOfTablesAccessed(tableNamesMap.size());
            }
      }

      private synchronized void createCalendarIfNeeded() {
            if (this.fastDateCal == null) {
                  this.fastDateCal = new GregorianCalendar(Locale.US);
                  this.fastDateCal.setTimeZone(this.getDefaultTimeZone());
            }
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Move to an absolute row number in the result set.
       * </p>
       * 
       * <p>
       * If row is positive, moves to an absolute row with respect to the
       * beginning of the result set. The first row is row 1, the second is row 2,
       * etc.
       * </p>
       * 
       * <p>
       * If row is negative, moves to an absolute row position with respect to the
       * end of result set. For example, calling absolute(-1) positions the cursor
       * on the last row, absolute(-2) indicates the next-to-last row, etc.
       * </p>
       * 
       * <p>
       * An attempt to position the cursor beyond the first/last row in the result
       * set, leaves the cursor before/after the first/last row, respectively.
       * </p>
       * 
       * <p>
       * Note: Calling absolute(1) is the same as calling first(). Calling
       * absolute(-1) is the same as calling last().
       * </p>
       * 
       * @param row
       *            the row number to move to
       * 
       * @return true if on the result set, false if off.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or row is 0, or result
       *                set type is TYPE_FORWARD_ONLY.
       */
00572       public boolean absolute(int row) throws SQLException {
            checkClosed();

            boolean b;

            if (this.rowData.size() == 0) {
                  b = false;
            } else {
                  if (row == 0) {
                        throw SQLError.createSQLException(
                                    Messages
                                                .getString("ResultSet.Cannot_absolute_position_to_row_0_110"), //$NON-NLS-1$
                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                  }

                  if (this.onInsertRow) {
                        this.onInsertRow = false;
                  }

                  if (this.doingUpdates) {
                        this.doingUpdates = false;
                  }

                  if (this.thisRow != null) {
                        this.thisRow.closeOpenStreams();
                  }
                  
                  if (row == 1) {
                        b = first();
                  } else if (row == -1) {
                        b = last();
                  } else if (row > this.rowData.size()) {
                        afterLast();
                        b = false;
                  } else {
                        if (row < 0) {
                              // adjust to reflect after end of result set
                              int newRowPosition = this.rowData.size() + row + 1;

                              if (newRowPosition <= 0) {
                                    beforeFirst();
                                    b = false;
                              } else {
                                    b = absolute(newRowPosition);
                              }
                        } else {
                              row--; // adjust for index difference
                              this.rowData.setCurrentRow(row);
                              this.thisRow = this.rowData.getAt(row);
                              b = true;
                        }
                  }
            }

            setRowPositionValidity();
            
            return b;
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Moves to the end of the result set, just after the last row. Has no
       * effect if the result set contains no rows.
       * </p>
       * 
       * @exception SQLException
       *                if a database-access error occurs, or result set type is
       *                TYPE_FORWARD_ONLY.
       */
00643       public void afterLast() throws SQLException {
            checkClosed();

            if (this.onInsertRow) {
                  this.onInsertRow = false;
            }

            if (this.doingUpdates) {
                  this.doingUpdates = false;
            }

            if (this.thisRow != null) {
                  this.thisRow.closeOpenStreams();
            }
            
            if (this.rowData.size() != 0) {
                  this.rowData.afterLast();
                  this.thisRow = null;
            }
            
            setRowPositionValidity();
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Moves to the front of the result set, just before the first row. Has no
       * effect if the result set contains no rows.
       * </p>
       * 
       * @exception SQLException
       *                if a database-access error occurs, or result set type is
       *                TYPE_FORWARD_ONLY
       */
00678       public void beforeFirst() throws SQLException {
            checkClosed();

            if (this.onInsertRow) {
                  this.onInsertRow = false;
            }

            if (this.doingUpdates) {
                  this.doingUpdates = false;
            }

            if (this.rowData.size() == 0) {
                  return;
            }

            if (this.thisRow != null) {
                  this.thisRow.closeOpenStreams();
            }
            
            this.rowData.beforeFirst();
            this.thisRow = null;
            
            setRowPositionValidity();
      }

      // ---------------------------------------------------------------------
      // Traversal/Positioning
      // ---------------------------------------------------------------------

      /**
       * Builds a hash between column names and their indices for fast retrieval.
       */
00710       public void buildIndexMapping() throws SQLException {
            int numFields = this.fields.length;
            this.columnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER);
            this.fullColumnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER);
            
            
            // We do this in reverse order, so that the 'first' column
            // with a given name ends up as the final mapping in the
            // hashtable...
            //
            // Quoting the JDBC Spec:
            //
            // "Column names used as input to getter
            // methods are case insensitive. When a getter method is called with a
            // column
            // name and several columns have the same name, the value of the first
            // matching column will be returned. "
            //
            for (int i = numFields - 1; i >= 0; i--) {
                  Integer index = Constants.integerValueOf(i);
                  String columnName = this.fields[i].getName();
                  String fullColumnName = this.fields[i].getFullName();

                  if (columnName != null) {                 
                        this.columnNameToIndex.put(columnName, index);
                  }

                  if (fullColumnName != null) {
                        this.fullColumnNameToIndex.put(fullColumnName, index);
                  }
            }

            // set the flag to prevent rebuilding...
            this.hasBuiltIndexMapping = true;
      }

      /**
       * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
       * updateXXX() method(s) and before calling updateRow() to rollback the
       * updates made to a row. If no updates have been made or updateRow() has
       * already been called, then this method has no effect.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or if called when on
       *                the insert row.
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
00758       public void cancelRowUpdates() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * Ensures that the result set is not closed
       * 
       * @throws SQLException
       *             if the result set is closed
       */
00768       protected final void checkClosed() throws SQLException {
            if (this.isClosed) {
                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$
                              SQLError.SQL_STATE_GENERAL_ERROR);
            }
      }

      /**
       * Checks if columnIndex is within the number of columns in this result set.
       * 
       * @param columnIndex
       *            the index to check
       * 
       * @throws SQLException
       *             if the index is out of bounds
       */
00786       protected final void checkColumnBounds(int columnIndex) throws SQLException {
            if ((columnIndex < 1)) {
                  throw SQLError.createSQLException(Messages.getString(
                              "ResultSet.Column_Index_out_of_range_low", new Object[] {
                                          Constants.integerValueOf(columnIndex),
                                          Constants.integerValueOf(this.fields.length) }),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            } else if ((columnIndex > this.fields.length)) {
                  throw SQLError.createSQLException(Messages.getString(
                              "ResultSet.Column_Index_out_of_range_high", new Object[] {
                                          Constants.integerValueOf(columnIndex),
                                          Constants.integerValueOf(this.fields.length) }),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }

            if (this.profileSql || this.useUsageAdvisor) {
                  this.columnUsed[columnIndex - 1] = true;
            }
      }

      /**
       * Ensures that the cursor is positioned on a valid row and that the result
       * set is not closed
       * 
       * @throws SQLException
       *             if the result set is not in a valid state for traversal
       */
00813       protected void checkRowPos() throws SQLException {
            checkClosed();

            if (!this.onValidRow) {
                  throw SQLError.createSQLException(this.invalidRowReason, 
                              SQLError.SQL_STATE_GENERAL_ERROR);
            }
      }
      
      private boolean onValidRow = false;
      private String invalidRowReason = null;
      
      private void setRowPositionValidity() throws SQLException {
            if (!this.rowData.isDynamic() && (this.rowData.size() == 0)) {
                  this.invalidRowReason = Messages
                  .getString("ResultSet.Illegal_operation_on_empty_result_set");//$NON-NLS-1$
                  this.onValidRow = false;
            } else if (this.rowData.isBeforeFirst()) {
                  this.invalidRowReason = Messages
                              .getString("ResultSet.Before_start_of_result_set_146"); //$NON-NLS-1$
                  this.onValidRow = false;
            } else if (this.rowData.isAfterLast()) {
                  this.invalidRowReason = Messages
                              .getString("ResultSet.After_end_of_result_set_148"); //$NON-NLS-1$
                  this.onValidRow = false;
            } else {
                  this.onValidRow = true;
                  this.invalidRowReason = null;
            }
      }

      /**
       * We can't do this ourselves, otherwise the contract for
       * Statement.getMoreResults() won't work correctly.
       */
00848       public void clearNextResult() {
            this.nextResultSet = null;
      }

      /**
       * After this call, getWarnings returns null until a new warning is reported
       * for this ResultSet
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
00859       public void clearWarnings() throws SQLException {
            this.warningChain = null;
      }

      /**
       * In some cases, it is desirable to immediately release a ResultSet
       * database and JDBC resources instead of waiting for this to happen when it
       * is automatically closed. The close method provides this immediate
       * release.
       * 
       * <p>
       * <B>Note:</B> A ResultSet is automatically closed by the Statement the
       * Statement that generated it when that Statement is closed, re-executed,
       * or is used to retrieve the next result from a sequence of multiple
       * results. A ResultSet is also automatically closed when it is garbage
       * collected.
       * </p>
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
00880       public void close() throws SQLException {
            realClose(true);
      }

      /**
       * @return
       */
00887       private int convertToZeroWithEmptyCheck() throws SQLException {
            if (this.connection.getEmptyStringsConvertToZero()) {
                  return 0;
            }

            throw SQLError.createSQLException("Can't convert empty string ('') to numeric",
                        SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
      }
      
      private String convertToZeroLiteralStringWithEmptyCheck()
            throws SQLException {
            
            if (this.connection.getEmptyStringsConvertToZero()) {
                  return "0";
            }

            throw SQLError.createSQLException("Can't convert empty string ('') to numeric",
                        SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
      }

      //
      // Note, row data is linked between these two result sets
      //
00910       public ResultSetInternalMethods copy() throws SQLException {
            ResultSetInternalMethods rs = ResultSetImpl.getInstance(this.catalog, this.fields, this.rowData,
                        this.connection, this.owningStatement, false); // note, doesn't work for updatable result sets

            return rs;
      }

00917       public void redefineFieldsForDBMD(Field[] f) {
            this.fields = f;
            
            for (int i = 0; i < this.fields.length; i++) {
                  this.fields[i].setUseOldNameMetadata(true);
                  this.fields[i].setConnection(this.connection);
            }
      }
      
      public void populateCachedMetaData(CachedResultSetMetaData cachedMetaData)
            throws SQLException {
            cachedMetaData.fields = this.fields;
            cachedMetaData.columnNameToIndex = this.columnNameToIndex;
            cachedMetaData.fullColumnNameToIndex = this.fullColumnNameToIndex;
            cachedMetaData.metadata = getMetaData();
      }
      
      public void initializeFromCachedMetaData(CachedResultSetMetaData cachedMetaData) {
            this.fields = cachedMetaData.fields;
            this.columnNameToIndex = cachedMetaData.columnNameToIndex;
            this.fullColumnNameToIndex = cachedMetaData.fullColumnNameToIndex;
            this.hasBuiltIndexMapping = true;
      }
      

      /**
       * JDBC 2.0 Delete the current row from the result set and the underlying
       * database. Cannot be called when on the insert row.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or if called when on
       *                the insert row.
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
00952       public void deleteRow() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * @param columnIndex
       * @param stringVal
       * @param mysqlType
       * @return
       * @throws SQLException
       */
00963       private String extractStringFromNativeColumn(int columnIndex, int mysqlType)
                  throws SQLException {
            int columnIndexMinusOne = columnIndex - 1;

            this.wasNullFlag = false;
            
            if (this.thisRow.isNull(columnIndexMinusOne)) {
                  this.wasNullFlag = true;
                  
                  return null;
            }

            this.wasNullFlag = false;

            String encoding = this.fields[columnIndexMinusOne]
                                                      .getCharacterSet();
            
            return this.thisRow.getString(columnIndex - 1, encoding, this.connection);
      }

      protected synchronized Date fastDateCreate(Calendar cal, int year, int month,
                  int day) {
            if (cal == null) {
                  createCalendarIfNeeded();
                  cal = this.fastDateCal;
            }

            boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();
                                    
            return TimeUtil.fastDateCreate(useGmtMillis,
                        useGmtMillis ? getGmtCalendar() : null,
                        cal, year, month, day);
      }

      protected synchronized Time fastTimeCreate(Calendar cal, int hour,
                  int minute, int second) throws SQLException {
            if (cal == null) {
                  createCalendarIfNeeded();
                  cal = this.fastDateCal;
            }

            return TimeUtil.fastTimeCreate(cal, hour, minute, second);
      }

      protected synchronized Timestamp fastTimestampCreate(Calendar cal, int year,
                  int month, int day, int hour, int minute, int seconds,
                  int secondsPart) {
            if (cal == null) {
                  createCalendarIfNeeded();
                  cal = this.fastDateCal;
            }

            boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();
            
            return TimeUtil.fastTimestampCreate(useGmtMillis,
                        useGmtMillis ? getGmtCalendar() : null,
                        cal, year, month, day, hour,
                        minute, seconds, secondsPart);
      }

      /*
      /**
       * Required by JDBC spec
       */
      /*
      protected void finalize() throws Throwable {
            if (!this.isClosed) {
                  realClose(false);
            }
      }
      */

      // --------------------------JDBC 2.0-----------------------------------
      // ---------------------------------------------------------------------
      // Getter's and Setter's
      // ---------------------------------------------------------------------


      /**
       * Map a ResultSet column name to a ResultSet column index
       * 
       * @param columnName
       *            the name of the column
       * 
       * @return the column index
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
01052       public synchronized int findColumn(String columnName) throws SQLException {
            Integer index;

            if (!this.hasBuiltIndexMapping) {
                  buildIndexMapping();
            }

            index = (Integer) this.columnNameToIndex.get(columnName);

            if (index == null) {
                  index = (Integer) this.fullColumnNameToIndex.get(columnName);
            }

            if (index != null) {
                  return index.intValue() + 1;
            }

            // Try this inefficient way, now

            for (int i = 0; i < this.fields.length; i++) {
                  if (this.fields[i].getName().equalsIgnoreCase(columnName)) {
                        return i + 1;
                  } else if (this.fields[i].getFullName()
                              .equalsIgnoreCase(columnName)) {
                        return i + 1;
                  }
            }

            throw SQLError.createSQLException(Messages.getString("ResultSet.Column____112")
                        + columnName
                        + Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$
                        SQLError.SQL_STATE_COLUMN_NOT_FOUND);
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Moves to the first row in the result set.
       * </p>
       * 
       * @return true if on a valid row, false if no rows in the result set.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or result set type is
       *                TYPE_FORWARD_ONLY.
       */
01099       public boolean first() throws SQLException {
            checkClosed();

            boolean b = true;
            
            if (this.rowData.isEmpty()) {
                  b = false;
            } else {
      
                  if (this.onInsertRow) {
                        this.onInsertRow = false;
                  }
      
                  if (this.doingUpdates) {
                        this.doingUpdates = false;
                  }
      
                  this.rowData.beforeFirst();
                  this.thisRow = this.rowData.next();
            }

            setRowPositionValidity();
            
            return b;
      }

      /**
       * JDBC 2.0 Get an array column.
       * 
       * @param i
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing an SQL array
       * 
       * @throws SQLException
       *             if a database error occurs
       * @throws NotImplemented
       *             DOCUMENT ME!
       */
01138       public java.sql.Array getArray(int i) throws SQLException {
            checkColumnBounds(i);
            
            throw new NotImplemented();
      }

      /**
       * JDBC 2.0 Get an array column.
       * 
       * @param colName
       *            the column name
       * 
       * @return an object representing an SQL array
       * 
       * @throws SQLException
       *             if a database error occurs
       * @throws NotImplemented
       *             DOCUMENT ME!
       */
01157       public java.sql.Array getArray(String colName) throws SQLException {
            return getArray(findColumn(colName));
      }

      /**
       * A column value can be retrieved as a stream of ASCII characters and then
       * read in chunks from the stream. This method is particulary suitable for
       * retrieving large LONGVARCHAR values. The JDBC driver will do any
       * necessary conversion from the database format into ASCII.
       * 
       * <p>
       * <B>Note:</B> All the data in the returned stream must be read prior to
       * getting the value of any other column. The next call to a get method
       * implicitly closes the stream. Also, a stream may return 0 for available()
       * whether there is data available or not.
       * </p>
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return a Java InputStream that delivers the database column value as a
       *         stream of one byte ASCII characters. If the value is SQL NULL
       *         then the result is null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @see getBinaryStream
       */
01186       public InputStream getAsciiStream(int columnIndex) throws SQLException {
            checkRowPos();

            if (!this.isBinaryEncoded) {
                  return getBinaryStream(columnIndex);
            }

            return getNativeBinaryStream(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
01207       public InputStream getAsciiStream(String columnName) throws SQLException {
            return getAsciiStream(findColumn(columnName));
      }

      /**
       * JDBC 2.0 Get the value of a column in the current row as a
       * java.math.BigDecimal object.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return the column value (full precision); if the value is SQL NULL, the
       *         result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
01224       public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  String stringVal = getString(columnIndex);
                  BigDecimal val;

                  if (stringVal != null) {
                        if (stringVal.length() == 0) {
                              
                              val = new BigDecimal(
                                          convertToZeroLiteralStringWithEmptyCheck());

                              return val;
                        }

                        try {
                              val = new BigDecimal(stringVal);

                              return val;
                        } catch (NumberFormatException ex) {
                              throw SQLError.createSQLException(Messages
                                          .getString("ResultSet.Bad_format_for_BigDecimal",
                                                      new Object[] { stringVal,
                                                                  Constants.integerValueOf(columnIndex) }),
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                        }
                  }

                  return null;
            }

            return getNativeBigDecimal(columnIndex);
      }

      /**
       * Get the value of a column in the current row as a java.math.BigDecimal
       * object
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * @param scale
       *            the number of digits to the right of the decimal
       * 
       * @return the column value; if the value is SQL NULL, null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @deprecated
       */
01273       public BigDecimal getBigDecimal(int columnIndex, int scale)
                  throws SQLException {
            if (!this.isBinaryEncoded) {
                  String stringVal = getString(columnIndex);
                  BigDecimal val;

                  if (stringVal != null) {
                        if (stringVal.length() == 0) {
                              val = new BigDecimal(
                                          convertToZeroLiteralStringWithEmptyCheck());

                              try {
                                    return val.setScale(scale);
                              } catch (ArithmeticException ex) {
                                    try {
                                          return val
                                                      .setScale(scale, BigDecimal.ROUND_HALF_UP);
                                    } catch (ArithmeticException arEx) {
                                          throw SQLError.createSQLException(
                                                      Messages
                                                                  .getString("ResultSet.Bad_format_for_BigDecimal____124") //$NON-NLS-1$
                                                                  + stringVal
                                                                  + Messages
                                                                              .getString("ResultSet.___in_column__125")
                                                                  + columnIndex
                                                                  + "(" //$NON-NLS-1$
                                                                  + this.fields[columnIndex - 1]
                                                                  + ").",
                                                      SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                                    }
                              }
                        }

                        try {
                              val = new BigDecimal(stringVal);
                        } catch (NumberFormatException ex) {
                              if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                                    long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);

                                    val = new BigDecimal(valueAsLong);
                              } else {
                                    throw SQLError.createSQLException(Messages
                                          .getString("ResultSet.Bad_format_for_BigDecimal",
                                                      new Object[] { Constants.integerValueOf(columnIndex),
                                                                  stringVal }),
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                                    }
                        }

                        try {
                              return val.setScale(scale);
                        } catch (ArithmeticException ex) {
                              try {
                                    return val.setScale(scale, BigDecimal.ROUND_HALF_UP);
                              } catch (ArithmeticException arithEx) {
                                    throw SQLError.createSQLException(Messages.getString(
                                                "ResultSet.Bad_format_for_BigDecimal",
                                                new Object[] { Constants.integerValueOf(columnIndex),
                                                            stringVal }),
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                              }
                        }
                  }

                  return null;
            }

            return getNativeBigDecimal(columnIndex, scale);
      }

      /**
       * JDBC 2.0 Get the value of a column in the current row as a
       * java.math.BigDecimal object.
       * 
       * @param columnName
       *            the name of the column to retrieve the value from
       * 
       * @return the BigDecimal value in the column
       * 
       * @throws SQLException
       *             if an error occurs
       */
01355       public BigDecimal getBigDecimal(String columnName) throws SQLException {
            return getBigDecimal(findColumn(columnName));
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * @param scale
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       * 
       * @deprecated
       */
01374       public BigDecimal getBigDecimal(String columnName, int scale)
                  throws SQLException {
            return getBigDecimal(findColumn(columnName), scale);
      }

      private final BigDecimal getBigDecimalFromString(String stringVal,
                  int columnIndex, int scale) throws SQLException {
            BigDecimal bdVal;

            if (stringVal != null) {
                  if (stringVal.length() == 0) {
                        bdVal = new BigDecimal(convertToZeroLiteralStringWithEmptyCheck());

                        try {
                              return bdVal.setScale(scale);
                        } catch (ArithmeticException ex) {
                              try {
                                    return bdVal.setScale(scale, BigDecimal.ROUND_HALF_UP);
                              } catch (ArithmeticException arEx) {
                                    throw new SQLException(Messages
                                                .getString("ResultSet.Bad_format_for_BigDecimal",
                                                            new Object[] { stringVal,
                                                                        Constants.integerValueOf(columnIndex) }),
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                              }
                        }
                  }

                  try {
                        try {
                              return new BigDecimal(stringVal).setScale(scale);
                        } catch (ArithmeticException ex) {
                              try {
                                    return new BigDecimal(stringVal).setScale(scale,
                                                BigDecimal.ROUND_HALF_UP);
                              } catch (ArithmeticException arEx) {
                                    throw new SQLException(Messages
                                                .getString("ResultSet.Bad_format_for_BigDecimal",
                                                            new Object[] { stringVal,
                                                                        Constants.integerValueOf(columnIndex) }),
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                              }
                        }
                  } catch (NumberFormatException ex) {
                        if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                              long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);

                              try {
                                    return new BigDecimal(valueAsLong).setScale(scale);
                              } catch (ArithmeticException arEx1) {
                                    try {
                                          return new BigDecimal(valueAsLong).setScale(scale,
                                                      BigDecimal.ROUND_HALF_UP);
                                    } catch (ArithmeticException arEx2) {
                                          throw new SQLException(Messages
                                                      .getString("ResultSet.Bad_format_for_BigDecimal",
                                                                  new Object[] { stringVal,
                                                                              Constants.integerValueOf(columnIndex) }),
                                                      SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                                    }
                              }
                        }
                        
                        if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TINY &&
                                    this.connection.getTinyInt1isBit() && this.fields[columnIndex - 1].getLength() == 1) {
                              return new BigDecimal(stringVal.equalsIgnoreCase("true") ? 1 : 0).setScale(scale);
                        }
                        
                        throw new SQLException(Messages
                                    .getString("ResultSet.Bad_format_for_BigDecimal",
                                                new Object[] { stringVal,
                                                            Constants.integerValueOf(columnIndex) }),
                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                  }
            }
            
            return null;
      }

      /**
       * A column value can also be retrieved as a binary stream. This method is
       * suitable for retrieving LONGVARBINARY values.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return a Java InputStream that delivers the database column value as a
       *         stream of bytes. If the value is SQL NULL, then the result is
       *         null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @see getAsciiStream
       * @see getUnicodeStream
       */
01470       public InputStream getBinaryStream(int columnIndex) throws SQLException {
            checkRowPos();

            if (!this.isBinaryEncoded) {
                  checkColumnBounds(columnIndex);
                  
                  int columnIndexMinusOne = columnIndex - 1;
                  
                  if (this.thisRow.isNull(columnIndexMinusOne)) {
                        this.wasNullFlag = true;
                        
                        return null;
                  }
                  
                  this.wasNullFlag = false;
                  
                  return this.thisRow.getBinaryInputStream(columnIndexMinusOne);
            }

            return getNativeBinaryStream(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
01503       public InputStream getBinaryStream(String columnName) throws SQLException {
            return getBinaryStream(findColumn(columnName));
      }

      /**
       * JDBC 2.0 Get a BLOB column.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing a BLOB
       * 
       * @throws SQLException
       *             if an error occurs.
       */
01518       public java.sql.Blob getBlob(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkRowPos();

                  checkColumnBounds(columnIndex);

                  int columnIndexMinusOne = columnIndex - 1;
                  
                  if (this.thisRow.isNull(columnIndexMinusOne)) {
                        this.wasNullFlag = true;
                  } else {
                        this.wasNullFlag = false;
                  }
                  
                  if (this.wasNullFlag) {
                        return null;
                  }

                  if (!this.connection.getEmulateLocators()) {
                        return new Blob(this.thisRow.getColumnValue(columnIndexMinusOne));
                  }

                  return new BlobFromLocator(this, columnIndex);
            }

            return getNativeBlob(columnIndex);
      }

      /**
       * JDBC 2.0 Get a BLOB column.
       * 
       * @param colName
       *            the column name
       * 
       * @return an object representing a BLOB
       * 
       * @throws SQLException
       *             if an error occurs.
       */
01557       public java.sql.Blob getBlob(String colName) throws SQLException {
            return getBlob(findColumn(colName));
      }

      /**
       * Get the value of a column in the current row as a Java boolean
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value, false for SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
01572       public boolean getBoolean(int columnIndex) throws SQLException {
            
            checkColumnBounds(columnIndex);

            //
            // MySQL 5.0 and newer have an actual BIT type,
            // so we need to check for that here...
            //

            int columnIndexMinusOne = columnIndex - 1;

            Field field = this.fields[columnIndexMinusOne];

            if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                  return byteArrayToBoolean(columnIndexMinusOne);
            }

            this.wasNullFlag = false;
            
            int sqlType = field.getSQLType();
            
            switch (sqlType) {
            case Types.BIT:
            case Types.BOOLEAN:
            case Types.TINYINT:
            case Types.SMALLINT:
            case Types.INTEGER:
            case Types.BIGINT:
            case Types.DECIMAL:
            case Types.NUMERIC:
            case Types.REAL:
            case Types.FLOAT:
            case Types.DOUBLE:
                  long boolVal = getLong(columnIndex, false);

                  return (boolVal == -1 || boolVal > 0);
            default:
                  if (this.connection.getPedantic()) {
                        // Table B-6 from JDBC spec
                        switch (sqlType) {
                        case Types.BINARY:
                        case Types.VARBINARY:
                        case Types.LONGVARBINARY:
                        case Types.DATE:
                        case Types.TIME:
                        case Types.TIMESTAMP:
                        case Types.CLOB:
                        case Types.BLOB:
                        case Types.ARRAY:
                        case Types.REF:
                        case Types.DATALINK:
                        case Types.STRUCT:
                        case Types.JAVA_OBJECT:
                              throw SQLError.createSQLException("Required type conversion not allowed",
                                          SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
                        }
                  }
            
                  if (sqlType == Types.BINARY ||
                        sqlType == Types.VARBINARY ||
                        sqlType == Types.LONGVARBINARY ||
                        sqlType == Types.BLOB) {
                        return byteArrayToBoolean(columnIndexMinusOne);
                  }
                  
                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getBoolean()", columnIndex,
                                    this.thisRow.getColumnValue(columnIndexMinusOne), this.fields[columnIndex],
                                    new int[] {
                                                MysqlDefs.FIELD_TYPE_BIT,
                                                MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }
            
                  String stringVal = getString(columnIndex);

                  return getBooleanFromString(stringVal, columnIndex);
            }
      }

      private boolean byteArrayToBoolean(int columnIndexMinusOne) throws SQLException {
            Object value = this.thisRow.getColumnValue(columnIndexMinusOne);
            
            if (value == null) {
                  this.wasNullFlag = true;

                  return false;
            }

            this.wasNullFlag = false;

            if (((byte[]) value).length == 0) {
                  return false;
            }

            byte boolVal = ((byte[]) value)[0];

            if (boolVal == (byte)'1') {
                  return true;
            } else if (boolVal == (byte)'0') {
                  return false;
            }
            
            return (boolVal == -1 || boolVal > 0);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
01693       public boolean getBoolean(String columnName) throws SQLException {
            return getBoolean(findColumn(columnName));
      }

      private final boolean getBooleanFromString(String stringVal, int columnIndex)
                  throws SQLException {
            if ((stringVal != null) && (stringVal.length() > 0)) {
                  int c = Character.toLowerCase(stringVal.charAt(0));

                  return ((c == 't') || (c == 'y') || (c == '1') || stringVal
                              .equals("-1"));
            }

            return false;
      }

      /**
       * Get the value of a column in the current row as a Java byte.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
01720       public byte getByte(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  String stringVal = getString(columnIndex);

                  if (this.wasNullFlag || (stringVal == null)) {
                        return 0;
                  }

                  return getByteFromString(stringVal, columnIndex);
            }

            return getNativeByte(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
01745       public byte getByte(String columnName) throws SQLException {
            return getByte(findColumn(columnName));
      }

      private final byte getByteFromString(String stringVal, int columnIndex)
                  throws SQLException {

            if (stringVal != null && stringVal.length() == 0) {
                  return (byte) convertToZeroWithEmptyCheck();
            }

            //
            // JDK-6 doesn't like trailing whitespace
            //
            // Note this isn't a performance issue, other
            // than the iteration over the string, as String.trim()
            // will return a new string only if whitespace is present
            //
            
            if (stringVal == null) {
                  return 0;
            }
            
            stringVal = stringVal.trim(); 
            
            try {
                  int decimalIndex = stringVal.indexOf(".");

                  
                  if (decimalIndex != -1) {
                        double valueAsDouble = Double.parseDouble(stringVal);

                        if (this.jdbcCompliantTruncationForReads) {
                              if (valueAsDouble < Byte.MIN_VALUE
                                          || valueAsDouble > Byte.MAX_VALUE) {
                                    throwRangeException(stringVal, columnIndex,
                                                Types.TINYINT);
                              }
                        }

                        return (byte) valueAsDouble;
                  }

                  long valueAsLong = Long.parseLong(stringVal);

                  if (this.jdbcCompliantTruncationForReads) {
                        if (valueAsLong < Byte.MIN_VALUE
                                    || valueAsLong > Byte.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsLong),
                                          columnIndex, Types.TINYINT);
                        }
                  }

                  return (byte) valueAsLong;
            } catch (NumberFormatException NFE) {
                  throw SQLError.createSQLException(
                              Messages.getString("ResultSet.Value____173")
                                          + stringVal //$NON-NLS-1$
                                          + Messages
                                                      .getString("ResultSet.___is_out_of_range_[-127,127]_174"),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * Get the value of a column in the current row as a Java byte array.
       * 
       * <p>
       * <b>Be warned</b> If the blob is huge, then you may run out of memory.
       * </p>
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
01824       public byte[] getBytes(int columnIndex) throws SQLException {
            return getBytes(columnIndex, false);
      }

      protected byte[] getBytes(int columnIndex, boolean noConversion)
                  throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkRowPos();
                  
                  checkColumnBounds(columnIndex);
                  
                  int columnIndexMinusOne = columnIndex - 1;

                  if (this.thisRow.isNull(columnIndexMinusOne)) {
                        this.wasNullFlag = true;
                  } else {
                        this.wasNullFlag = false;
                  }

                  if (this.wasNullFlag) {
                        return null;
                  }

                  return this.thisRow.getColumnValue(columnIndexMinusOne);
            }

            return getNativeBytes(columnIndex, noConversion);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
01864       public byte[] getBytes(String columnName) throws SQLException {
            return getBytes(findColumn(columnName));
      }

      private final byte[] getBytesFromString(String stringVal, int columnIndex)
                  throws SQLException {
            if (stringVal != null) {
                  return StringUtils.getBytes(stringVal, this.connection
                              .getEncoding(), this.connection
                              .getServerCharacterEncoding(), this.connection
                              .parserKnowsUnicode(),
                              this.connection);
            }

            return null;
      }

      /**
       * Optimization to only use one calendar per-session, or calculate it for
       * each call, depending on user configuration
       */
01885       protected Calendar getCalendarInstanceForSessionOrNew() {
            if (this.connection != null) {
                  return this.connection.getCalendarInstanceForSessionOrNew();
            } else {
                  // punt, no connection around
                  return new GregorianCalendar();
            }
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Get the value of a column in the current row as a java.io.Reader.
       * </p>
       * 
       * @param columnIndex
       *            the column to get the value from
       * 
       * @return the value in the column as a java.io.Reader.
       * 
       * @throws SQLException
       *             if an error occurs
       */
01909       public java.io.Reader getCharacterStream(int columnIndex)
                  throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkColumnBounds(columnIndex);
                  
                  int columnIndexMinusOne = columnIndex - 1;
                  
                  if (this.thisRow.isNull(columnIndexMinusOne)) {
                        this.wasNullFlag = true;
                        
                        return null;
                  }
                  
                  this.wasNullFlag = false;
                  
                  return this.thisRow.getReader(columnIndexMinusOne);
            }

            return getNativeCharacterStream(columnIndex);
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Get the value of a column in the current row as a java.io.Reader.
       * </p>
       * 
       * @param columnName
       *            the column name to retrieve the value from
       * 
       * @return the value as a java.io.Reader
       * 
       * @throws SQLException
       *             if an error occurs
       */
01945       public java.io.Reader getCharacterStream(String columnName)
                  throws SQLException {
            return getCharacterStream(findColumn(columnName));
      }

      private final java.io.Reader getCharacterStreamFromString(String stringVal,
                  int columnIndex) throws SQLException {
            if (stringVal != null) {
                  return new StringReader(stringVal);
            }

            return null;
      }

      /**
       * JDBC 2.0 Get a CLOB column.
       * 
       * @param i
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing a CLOB
       * 
       * @throws SQLException
       *             if an error occurs
       */
01970       public java.sql.Clob getClob(int i) throws SQLException {
            if (!this.isBinaryEncoded) {
                  String asString = getStringForClob(i);
                  
                  if (asString == null) {
                        return null;
                  }

                  return new com.mysql.jdbc.Clob(asString);
            }

            return getNativeClob(i);
      }

      /**
       * JDBC 2.0 Get a CLOB column.
       * 
       * @param colName
       *            the column name
       * 
       * @return an object representing a CLOB
       * 
       * @throws SQLException
       *             if an error occurs
       */
01995       public java.sql.Clob getClob(String colName) throws SQLException {
            return getClob(findColumn(colName));
      }

      private final java.sql.Clob getClobFromString(String stringVal,
                  int columnIndex) throws SQLException {
            return new com.mysql.jdbc.Clob(stringVal);
      }

      /**
       * JDBC 2.0 Return the concurrency of this result set. The concurrency used
       * is determined by the statement that created the result set.
       * 
       * @return the concurrency type, CONCUR_READ_ONLY, etc.
       * 
       * @throws SQLException
       *             if a database-access error occurs
       */
02013       public int getConcurrency() throws SQLException {
            return (CONCUR_READ_ONLY);
      }

      /**
       * Get the name of the SQL cursor used by this ResultSet
       * 
       * <p>
       * In SQL, a result table is retrieved though a cursor that is named. The
       * current row of a result can be updated or deleted using a positioned
       * update/delete statement that references the cursor name.
       * </p>
       * 
       * <p>
       * JDBC supports this SQL feature by providing the name of the SQL cursor
       * used by a ResultSet. The current row of a ResulSet is also the current
       * row of this SQL cursor.
       * </p>
       * 
       * <p>
       * <B>Note:</B> If positioned update is not supported, a SQLException is
       * thrown.
       * </p>
       * 
       * @return the ResultSet's SQL cursor name.
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
02042       public String getCursorName() throws SQLException {
            throw SQLError.createSQLException(Messages
                        .getString("ResultSet.Positioned_Update_not_supported"),
                        SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); //$NON-NLS-1$
      }

      /**
       * Get the value of a column in the current row as a java.sql.Date object
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value; null if SQL NULL
       * 
       * @exception java.sql.SQLException
       *                if a database access error occurs
       */
02059       public java.sql.Date getDate(int columnIndex) throws java.sql.SQLException {
            return getDate(columnIndex, null);
      }

      /**
       * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
       * object. Use the calendar to construct an appropriate millisecond value
       * for the Date, if the underlying database doesn't store timezone
       * information.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param cal
       *            the calendar to use in constructing the date
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
02079       public java.sql.Date getDate(int columnIndex, Calendar cal)
                  throws SQLException {
            if (this.isBinaryEncoded) {
                  return getNativeDate(columnIndex, (cal != null) ? cal.getTimeZone()
                              : this.getDefaultTimeZone());
            }

            if (!this.useFastDateParsing) {
                  String stringVal = getStringInternal(columnIndex, false);

                  if (stringVal == null) {
                        return null;
                  }
                  
                  return getDateFromString(stringVal, columnIndex);
            }
            
            checkColumnBounds(columnIndex);
            
            int columnIndexMinusOne = columnIndex - 1;
            
            if (this.thisRow.isNull(columnIndexMinusOne)) {
                  this.wasNullFlag = true;
                  
                  return null;
            }
            
            this.wasNullFlag = false;
            
            return this.thisRow.getDateFast(columnIndexMinusOne, this.connection, this);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws java.sql.SQLException
       *             DOCUMENT ME!
       */
02122       public java.sql.Date getDate(String columnName)
                  throws java.sql.SQLException {
            return getDate(findColumn(columnName));
      }

      /**
       * Get the value of a column in the current row as a java.sql.Date object.
       * Use the calendar to construct an appropriate millisecond value for the
       * Date, if the underlying database doesn't store timezone information.
       * 
       * @param columnName
       *            is the SQL name of the column
       * @param cal
       *            the calendar to use in constructing the date
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
02142       public java.sql.Date getDate(String columnName, Calendar cal)
                  throws SQLException {
            return getDate(findColumn(columnName), cal);
      }

      private final java.sql.Date getDateFromString(String stringVal,
                  int columnIndex) throws SQLException {
            int year = 0;
            int month = 0;
            int day = 0;

            try {
                  this.wasNullFlag = false;

                  if (stringVal == null) {
                        this.wasNullFlag = true;

                        return null;
                  }
                  
                  //
                  // JDK-6 doesn't like trailing whitespace
                  //
                  // Note this isn't a performance issue, other
                  // than the iteration over the string, as String.trim()
                  // will return a new string only if whitespace is present
                  //
                  
                  stringVal = stringVal.trim();

                  if (stringVal.equals("0") || stringVal.equals("0000-00-00")
                              || stringVal.equals("0000-00-00 00:00:00")
                              || stringVal.equals("00000000000000")
                              || stringVal.equals("0")) {

                        if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                    .equals(this.connection.getZeroDateTimeBehavior())) {
                              this.wasNullFlag = true;

                              return null;
                        } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                    .equals(this.connection.getZeroDateTimeBehavior())) {
                              throw SQLError.createSQLException("Value '" + stringVal
                                          + "' can not be represented as java.sql.Date",
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        }

                        // We're left with the case of 'round' to a date Java _can_
                        // represent, which is '0001-01-01'.
                        return fastDateCreate(null, 1, 1, 1);

                  } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
                        // Convert from TIMESTAMP
                        switch (stringVal.length()) {
                        case 21:
                        case 19: { // java.sql.Timestamp format
                              year = Integer.parseInt(stringVal.substring(0, 4));
                              month = Integer.parseInt(stringVal.substring(5, 7));
                              day = Integer.parseInt(stringVal.substring(8, 10));

                              return fastDateCreate(null, year, month, day);
                        }

                        case 14:
                        case 8: {
                              year = Integer.parseInt(stringVal.substring(0, 4));
                              month = Integer.parseInt(stringVal.substring(4, 6));
                              day = Integer.parseInt(stringVal.substring(6, 8));

                              return fastDateCreate(null, year, month, day);
                        }

                        case 12:
                        case 10:
                        case 6: {
                              year = Integer.parseInt(stringVal.substring(0, 2));

                              if (year <= 69) {
                                    year = year + 100;
                              }

                              month = Integer.parseInt(stringVal.substring(2, 4));
                              day = Integer.parseInt(stringVal.substring(4, 6));

                              return fastDateCreate(null, year + 1900, month, day);
                        }

                        case 4: {
                              year = Integer.parseInt(stringVal.substring(0, 4));

                              if (year <= 69) {
                                    year = year + 100;
                              }

                              month = Integer.parseInt(stringVal.substring(2, 4));

                              return fastDateCreate(null, year + 1900, month, 1);
                        }

                        case 2: {
                              year = Integer.parseInt(stringVal.substring(0, 2));

                              if (year <= 69) {
                                    year = year + 100;
                              }

                              return fastDateCreate(null, year + 1900, 1, 1);
                        }

                        default:
                              throw SQLError.createSQLException(Messages.getString(
                                          "ResultSet.Bad_format_for_Date", new Object[] {
                                                      stringVal, Constants.integerValueOf(columnIndex) }),
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                        } /* endswitch */
                  } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {

                        if (stringVal.length() == 2 || stringVal.length() == 1) {
                              year = Integer.parseInt(stringVal);

                              if (year <= 69) {
                                    year = year + 100;
                              }

                              year += 1900;
                        } else {
                              year = Integer.parseInt(stringVal.substring(0, 4));
                        }

                        return fastDateCreate(null, year, 1, 1);
                  } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
                        return fastDateCreate(null, 1970, 1, 1); // Return EPOCH
                  } else {
                        if (stringVal.length() < 10) {
                              if (stringVal.length() == 8) {
                                    return fastDateCreate(null, 1970, 1, 1); // Return EPOCH for TIME
                              }
                              
                              throw SQLError.createSQLException(Messages.getString(
                                          "ResultSet.Bad_format_for_Date", new Object[] {
                                                      stringVal, Constants.integerValueOf(columnIndex) }),
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                        }

                        if (stringVal.length() != 18) {
                              year = Integer.parseInt(stringVal.substring(0, 4));
                              month = Integer.parseInt(stringVal.substring(5, 7));
                              day = Integer.parseInt(stringVal.substring(8, 10));
                        } else {
                              // JDK-1.3 timestamp format, not real easy to parse positionally :p
                              StringTokenizer st = new StringTokenizer(stringVal, "- ");
                              
                              year = Integer.parseInt(st.nextToken());
                              month = Integer.parseInt(st.nextToken());
                              day = Integer.parseInt(st.nextToken());
                        }
                  }

                  return fastDateCreate(null, year, month, day);
            } catch (SQLException sqlEx) {
                  throw sqlEx; // don't re-wrap
            } catch (Exception e) {
                  throw SQLError.createSQLException(Messages.getString(
                              "ResultSet.Bad_format_for_Date", new Object[] { stringVal,
                                          Constants.integerValueOf(columnIndex) }),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }
      
      private TimeZone getDefaultTimeZone() {
            return this.connection.getDefaultTimeZone();
      }

      /**
       * Get the value of a column in the current row as a Java double.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
02326       public double getDouble(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  return getDoubleInternal(columnIndex);
            }

            return getNativeDouble(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
02345       public double getDouble(String columnName) throws SQLException {
            return getDouble(findColumn(columnName));
      }

      private final double getDoubleFromString(String stringVal, int columnIndex)
                  throws SQLException {
            return getDoubleInternal(stringVal, columnIndex);
      }

      /**
       * Converts a string representation of a number to a double. Need a faster
       * way to do this.
       * 
       * @param colIndex
       *            the 1-based index of the column to retrieve a double from.
       * 
       * @return the double value represented by the string in buf
       * 
       * @throws SQLException
       *             if an error occurs
       */
02366       protected double getDoubleInternal(int colIndex) throws SQLException {
            return getDoubleInternal(getString(colIndex), colIndex);
      }

      /**
       * Converts a string representation of a number to a double. Need a faster
       * way to do this.
       * 
       * @param stringVal
       *            the double as a String
       * @param colIndex
       *            the 1-based index of the column to retrieve a double from.
       * 
       * @return the double value represented by the string in buf
       * 
       * @throws SQLException
       *             if an error occurs
       */
02384       protected double getDoubleInternal(String stringVal, int colIndex)
                  throws SQLException {
            try {
                  if ((stringVal == null)) {
                        return 0;
                  }

                  if (stringVal.length() == 0) {
                        return convertToZeroWithEmptyCheck();
                  }

                  double d = Double.parseDouble(stringVal);

                  if (this.useStrictFloatingPoint) {
                        // Fix endpoint rounding precision loss in MySQL server
                        if (d == 2.147483648E9) {
                              // Fix Odd end-point rounding on MySQL
                              d = 2.147483647E9;
                        } else if (d == 1.0000000036275E-15) {
                              // Fix odd end-point rounding on MySQL
                              d = 1.0E-15;
                        } else if (d == 9.999999869911E14) {
                              d = 9.99999999999999E14;
                        } else if (d == 1.4012984643248E-45) {
                              d = 1.4E-45;
                        } else if (d == 1.4013E-45) {
                              d = 1.4E-45;
                        } else if (d == 3.4028234663853E37) {
                              d = 3.4028235E37;
                        } else if (d == -2.14748E9) {
                              d = -2.147483648E9;
                        } else if (d == 3.40282E37) {
                              d = 3.4028235E37;
                        }
                  }

                  return d;
            } catch (NumberFormatException e) {
                  if (this.fields[colIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                        long valueAsLong = getNumericRepresentationOfSQLBitType(colIndex);
                        
                        return valueAsLong;
                  }
                  
                  throw SQLError.createSQLException(Messages.getString(
                              "ResultSet.Bad_format_for_number", new Object[] {
                                          stringVal, Constants.integerValueOf(colIndex) }),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
            }
      }

      /**
       * JDBC 2.0 Returns the fetch direction for this result set.
       * 
       * @return the fetch direction for this result set.
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
02443       public int getFetchDirection() throws SQLException {
            return this.fetchDirection;
      }

      /**
       * JDBC 2.0 Return the fetch size for this result set.
       * 
       * @return the fetch size for this result set.
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
02455       public int getFetchSize() throws SQLException {
            return this.fetchSize;
      }

      /**
       * Returns the first character of the query that this result set was created
       * from.
       * 
       * @return the first character of the query...uppercased
       */
02465       public char getFirstCharOfQuery() {
            return this.firstCharOfQuery;
      }

      /**
       * Get the value of a column in the current row as a Java float.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
02480       public float getFloat(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  String val = null;

                  val = getString(columnIndex);

                  return getFloatFromString(val, columnIndex);
            }

            return getNativeFloat(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
02503       public float getFloat(String columnName) throws SQLException {
            return getFloat(findColumn(columnName));
      }

      private final float getFloatFromString(String val, int columnIndex)
                  throws SQLException {
            try {
                  if ((val != null)) {
                        if (val.length() == 0) {
                              return convertToZeroWithEmptyCheck();
                        }

                        float f = Float.parseFloat(val);

                        if (this.jdbcCompliantTruncationForReads) {
                              if (f == Float.MIN_VALUE || f == Float.MAX_VALUE) {
                                    double valAsDouble = Double.parseDouble(val);

                                    // Straight comparison is not reliable when at
                                    // absolute endpoints of Float.MIN_VALUE or 
                                    // Float.MAX_VALUE, so use epsillons with DOUBLEs

                              if ((valAsDouble < Float.MIN_VALUE - MIN_DIFF_PREC)
                                  || (valAsDouble > Float.MAX_VALUE - MAX_DIFF_PREC)) {
                                throwRangeException(String.valueOf(valAsDouble), columnIndex,
                                    Types.FLOAT);
                              }
                              }
                        }

                        return f;
                  }

                  return 0; // for NULL
            } catch (NumberFormatException nfe) {
                  try {
                        Double valueAsDouble = new Double(val);
                        float valueAsFloat = valueAsDouble.floatValue();
                        
                        if (this.jdbcCompliantTruncationForReads) {

                              if (this.jdbcCompliantTruncationForReads && 
                                          valueAsFloat == Float.NEGATIVE_INFINITY ||
                                          valueAsFloat == Float.POSITIVE_INFINITY) {
                                    throwRangeException(valueAsDouble.toString(), 
                                                columnIndex, Types.FLOAT);
                              }
                        }

                        return valueAsFloat;
                  } catch (NumberFormatException newNfe) {
                        ; // ignore, it's not a number
                  }

                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Invalid_value_for_getFloat()_-____200")
                                          + val //$NON-NLS-1$
                                          + Messages.getString("ResultSet.___in_column__201")
                                          + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * Get the value of a column in the current row as a Java int.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
02577       public int getInt(int columnIndex) throws SQLException {
            checkRowPos();

            if (!this.isBinaryEncoded) {
                  int columnIndexMinusOne = columnIndex - 1;
                  if (this.useFastIntParsing) {
                        checkColumnBounds(columnIndex);

                        if (this.thisRow.isNull(columnIndexMinusOne)) {
                              this.wasNullFlag = true;
                        } else {
                              this.wasNullFlag = false;
                        }

                        if (this.wasNullFlag) {
                              return 0;
                        }

                        if (this.thisRow.length(columnIndexMinusOne) == 0) {
                              return convertToZeroWithEmptyCheck();
                        }

                        boolean needsFullParse = this.thisRow
                                    .isFloatingPointNumber(columnIndexMinusOne);

                        if (!needsFullParse) {
                              try {
                                    return getIntWithOverflowCheck(columnIndexMinusOne);
                              } catch (NumberFormatException nfe) {
                                    try {

                                          return parseIntAsDouble(columnIndex, this.thisRow
                                                      .getString(columnIndexMinusOne,
                                                                  this.fields[columnIndexMinusOne]
                                                                              .getCharacterSet(),
                                                                  this.connection));
                                    } catch (NumberFormatException newNfe) {
                                          // ignore, it's not a number
                                    }

                                    if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                                          long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);

                                          if (this.connection
                                                      .getJdbcCompliantTruncationForReads()
                                                      && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
                                                throwRangeException(
                                                            String.valueOf(valueAsLong),
                                                            columnIndex, Types.INTEGER);
                                          }

                                          return (int) valueAsLong;
                                    }

                                    throw SQLError
                                                .createSQLException(
                                                            Messages
                                                                        .getString("ResultSet.Invalid_value_for_getInt()_-____74")
                                                                        + this.thisRow
                                                                                    .getString(
                                                                                                columnIndexMinusOne,
                                                                                                this.fields[columnIndexMinusOne]
                                                                                                            .getCharacterSet(),
                                                                                                this.connection) //$NON-NLS-1$
                                                                        + "'",
                                                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                        }
                  }

                  String val = null;

                  try {
                        val = getString(columnIndex);

                        if ((val != null)) {
                              if (val.length() == 0) {
                                    return convertToZeroWithEmptyCheck();
                              }

                              if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
                                          && (val.indexOf(".") == -1)) {
                                    int intVal = Integer.parseInt(val);
                                    
                                    checkForIntegerTruncation(columnIndex, null, val, intVal);
                                    
                                    return intVal;
                              }

                              // Convert floating point
                              int intVal =  parseIntAsDouble(columnIndex, val);
                              
                              checkForIntegerTruncation(columnIndex, null, val, intVal);
                              
                              return intVal;
                        }

                        return 0;
                  } catch (NumberFormatException nfe) {
                        try {
                              return parseIntAsDouble(columnIndex, val);
                        } catch (NumberFormatException newNfe) {
                              ; // ignore, it's not a number
                        }

                        if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                              long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);

                              if (this.jdbcCompliantTruncationForReads
                                          && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
                                    throwRangeException(String.valueOf(valueAsLong),
                                                columnIndex, Types.INTEGER);
                              }

                              return (int) valueAsLong;
                        }

                        throw SQLError
                                    .createSQLException(
                                                Messages
                                                            .getString("ResultSet.Invalid_value_for_getInt()_-____74")
                                                            + val //$NON-NLS-1$
                                                            + "'",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                  }
            }

            return getNativeInt(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
02718       public int getInt(String columnName) throws SQLException {
            return getInt(findColumn(columnName));
      }

      private final int getIntFromString(String val, int columnIndex)
                  throws SQLException {
            try {
                  if ((val != null)) {

                        if (val.length() == 0) {
                              return convertToZeroWithEmptyCheck();
                        }

                        if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
                                    && (val.indexOf(".") == -1)) {
                              //
                              // JDK-6 doesn't like trailing whitespace
                              //
                              // Note this isn't a performance issue, other
                              // than the iteration over the string, as String.trim()
                              // will return a new string only if whitespace is present
                              //
                              
                              val = val.trim(); 
                              
                              int valueAsInt = Integer.parseInt(val);

                              if (this.jdbcCompliantTruncationForReads) {
                                    if (valueAsInt == Integer.MIN_VALUE
                                                || valueAsInt == Integer.MAX_VALUE) {
                                          long valueAsLong = Long.parseLong(val);

                                          if (valueAsLong < Integer.MIN_VALUE
                                                      || valueAsLong > Integer.MAX_VALUE) {
                                                throwRangeException(
                                                            String.valueOf(valueAsLong),
                                                            columnIndex, Types.INTEGER);
                                          }
                                    }
                              }

                              return valueAsInt;
                        }

                        // Convert floating point

                        double valueAsDouble = Double.parseDouble(val);

                        if (this.jdbcCompliantTruncationForReads) {
                              if (valueAsDouble < Integer.MIN_VALUE
                                          || valueAsDouble > Integer.MAX_VALUE) {
                                    throwRangeException(String.valueOf(valueAsDouble),
                                                columnIndex, Types.INTEGER);
                              }
                        }

                        return (int) valueAsDouble;
                  }

                  return 0; // for NULL
            } catch (NumberFormatException nfe) {
                  try {
                        double valueAsDouble = Double.parseDouble(val);

                        if (this.jdbcCompliantTruncationForReads) {
                              if (valueAsDouble < Integer.MIN_VALUE
                                          || valueAsDouble > Integer.MAX_VALUE) {
                                    throwRangeException(String.valueOf(valueAsDouble),
                                                columnIndex, Types.INTEGER);
                              }
                        }

                        return (int) valueAsDouble;
                  } catch (NumberFormatException newNfe) {
                        ; // ignore, it's not a number
                  }

                  throw SQLError.createSQLException(Messages
                              .getString("ResultSet.Invalid_value_for_getInt()_-____206")
                              + val //$NON-NLS-1$
                              + Messages.getString("ResultSet.___in_column__207")
                              + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * Get the value of a column in the current row as a Java long.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
02814       public long getLong(int columnIndex) throws SQLException {
            return getLong(columnIndex, true);
      }
      
      private long getLong(int columnIndex, boolean overflowCheck) throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkRowPos();
                  
                  int columnIndexMinusOne = columnIndex - 1;
                  
                  if (this.useFastIntParsing) {
                  
                        checkColumnBounds(columnIndex);

                        if (this.thisRow.isNull(columnIndexMinusOne)) {
                              this.wasNullFlag = true;
                        } else {
                              this.wasNullFlag = false;
                        }
                        
                        if (this.wasNullFlag) {
                              return 0;
                        }

                        if (this.thisRow.length(columnIndexMinusOne) == 0) {
                              return convertToZeroWithEmptyCheck();
                        }

                        boolean needsFullParse = this.thisRow.isFloatingPointNumber(columnIndexMinusOne);

                        if (!needsFullParse) {
                              try {
                                    return getLongWithOverflowCheck(columnIndexMinusOne, overflowCheck);
                              } catch (NumberFormatException nfe) {
                                    try {
                                          // To do: Warn of over/underflow???
                                          return parseLongAsDouble(columnIndex, this.thisRow
                                                      .getString(columnIndexMinusOne,
                                                                  this.fields[columnIndexMinusOne]
                                                                              .getCharacterSet(),
                                                                  this.connection));
                                    } catch (NumberFormatException newNfe) {
                                          // ; // ignore, it's not a number
                                    }

                                    if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                                          return getNumericRepresentationOfSQLBitType(columnIndex);
                                    }
                                    
                                    throw SQLError.createSQLException(
                                                Messages
                                                            .getString("ResultSet.Invalid_value_for_getLong()_-____79")
                                                            + this.thisRow
                                                            .getString(columnIndexMinusOne,
                                                                        this.fields[columnIndexMinusOne]
                                                                                    .getCharacterSet(),
                                                                        this.connection) //$NON-NLS-1$
                                                            + "'",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                        }
                  }

                  String val = null;

                  try {
                        val = getString(columnIndex);

                        if ((val != null)) {
                              if (val.length() == 0) {
                                    return convertToZeroWithEmptyCheck();
                              }

                              if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
                                    return parseLongWithOverflowCheck(columnIndex, null,
                                                val, overflowCheck);
                              }

                              // Convert floating point
                              return parseLongAsDouble(columnIndex, val);
                        }

                        return 0; // for NULL
                  } catch (NumberFormatException nfe) {
                        try {
                              return parseLongAsDouble(columnIndex, val);
                        } catch (NumberFormatException newNfe) {
                              // ; // ignore, it's not a number
                        }

                        throw SQLError.createSQLException(
                                    Messages
                                                .getString("ResultSet.Invalid_value_for_getLong()_-____79")
                                                + val //$NON-NLS-1$
                                                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                  }
            }

            return getNativeLong(columnIndex, overflowCheck, true);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
02926       public long getLong(String columnName) throws SQLException {
            return getLong(findColumn(columnName));
      }

      private final long getLongFromString(String val, int columnIndex)
                  throws SQLException {
            try {
                  if ((val != null)) {

                        if (val.length() == 0) {
                              return convertToZeroWithEmptyCheck();
                        }

                        if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
                              return parseLongWithOverflowCheck(columnIndex, null, val, true);
                        }

                        // Convert floating point
                        return parseLongAsDouble(columnIndex, val);
                  }

                  return 0; // for NULL
            } catch (NumberFormatException nfe) {
                  try {
                        // To do: Warn of over/underflow???
                        return parseLongAsDouble(columnIndex, val);
                  } catch (NumberFormatException newNfe) {
                        ; // ignore, it's not a number
                  }

                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Invalid_value_for_getLong()_-____211")
                                          + val //$NON-NLS-1$
                                          + Messages.getString("ResultSet.___in_column__212")
                                          + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * The numbers, types and properties of a ResultSet's columns are provided
       * by the getMetaData method
       * 
       * @return a description of the ResultSet's columns
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
02974       public java.sql.ResultSetMetaData getMetaData() throws SQLException {
            checkClosed();

            return new com.mysql.jdbc.ResultSetMetaData(this.fields,
                        this.connection.getUseOldAliasMetadataBehavior());
      }

      /**
       * JDBC 2.0 Get an array column.
       * 
       * @param i
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing an SQL array
       * 
       * @throws SQLException
       *             if a database error occurs
       * @throws NotImplemented
       *             DOCUMENT ME!
       */
02994       protected java.sql.Array getNativeArray(int i) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * A column value can be retrieved as a stream of ASCII characters and then
       * read in chunks from the stream. This method is particulary suitable for
       * retrieving large LONGVARCHAR values. The JDBC driver will do any
       * necessary conversion from the database format into ASCII.
       * 
       * <p>
       * <B>Note:</B> All the data in the returned stream must be read prior to
       * getting the value of any other column. The next call to a get method
       * implicitly closes the stream. Also, a stream may return 0 for available()
       * whether there is data available or not.
       * </p>
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return a Java InputStream that delivers the database column value as a
       *         stream of one byte ASCII characters. If the value is SQL NULL
       *         then the result is null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @see getBinaryStream
       */
03023       protected InputStream getNativeAsciiStream(int columnIndex)
                  throws SQLException {
            checkRowPos();

            return getNativeBinaryStream(columnIndex);
      }

      /**
       * JDBC 2.0 Get the value of a column in the current row as a
       * java.math.BigDecimal object.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return the column value (full precision); if the value is SQL NULL, the
       *         result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
03043       protected BigDecimal getNativeBigDecimal(int columnIndex)
                  throws SQLException {

            checkColumnBounds(columnIndex);
            
            int scale = this.fields[columnIndex - 1].getDecimals();
            
            return getNativeBigDecimal(columnIndex, scale);
      }

      /**
       * Get the value of a column in the current row as a java.math.BigDecimal
       * object
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * @param scale
       *            the number of digits to the right of the decimal
       * 
       * @return the column value; if the value is SQL NULL, null
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
03067       protected BigDecimal getNativeBigDecimal(int columnIndex, int scale)
                  throws SQLException {
            checkColumnBounds(columnIndex);
            
            String stringVal = null;
            
            Field f = this.fields[columnIndex - 1];
            
            Object value = this.thisRow.getColumnValue(columnIndex - 1);
            
            if (value == null) {
                  this.wasNullFlag = true;
                  
                  return null;
            }
            
            this.wasNullFlag = false;
            
            switch (f.getSQLType()) {
                  case Types.DECIMAL:
                  case Types.NUMERIC:
                        stringVal = StringUtils
                                    .toAsciiString((byte[]) value);
                        break;
                  default:
                        stringVal = getNativeString(columnIndex);
            }

            return getBigDecimalFromString(stringVal, columnIndex, scale);
      }

      /**
       * A column value can also be retrieved as a binary stream. This method is
       * suitable for retrieving LONGVARBINARY values.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return a Java InputStream that delivers the database column value as a
       *         stream of bytes. If the value is SQL NULL, then the result is
       *         null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @see getAsciiStream
       * @see getUnicodeStream
       */
03115       protected InputStream getNativeBinaryStream(int columnIndex)
                  throws SQLException {
            checkRowPos();

            int columnIndexMinusOne = columnIndex - 1;
            
            if (this.thisRow.isNull(columnIndexMinusOne)) {
                  this.wasNullFlag = true;
                  
                  return null;
            }
            
            this.wasNullFlag = false;
            
            switch (this.fields[columnIndexMinusOne].getSQLType()) {
            case Types.BIT:
            case Types.BINARY:
            case Types.VARBINARY:
            case Types.BLOB:
            case Types.LONGVARBINARY:
                  return this.thisRow.getBinaryInputStream(columnIndexMinusOne);
            }
            
            byte[] b = getNativeBytes(columnIndex, false);

            if (b != null) {
                  return new ByteArrayInputStream(b);
            }

            return null;
      }

      /**
       * JDBC 2.0 Get a BLOB column.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing a BLOB
       * 
       * @throws SQLException
       *             if an error occurs.
       */
03158       protected java.sql.Blob getNativeBlob(int columnIndex) throws SQLException {
            checkRowPos();

            checkColumnBounds(columnIndex);

            Object value = this.thisRow.getColumnValue(columnIndex - 1);
            
            if (value == null) {
                  this.wasNullFlag = true;
            } else {
                  this.wasNullFlag = false;
            }

            if (this.wasNullFlag) {
                  return null;
            }

            int mysqlType = this.fields[columnIndex - 1].getMysqlType();

            byte[] dataAsBytes = null;

            switch (mysqlType) {
            case MysqlDefs.FIELD_TYPE_TINY_BLOB:
            case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
            case MysqlDefs.FIELD_TYPE_LONG_BLOB:
            case MysqlDefs.FIELD_TYPE_BLOB:
                  dataAsBytes = (byte[]) value;
                  break;

            default:
                  dataAsBytes = getNativeBytes(columnIndex, false);
            }

            if (!this.connection.getEmulateLocators()) {
                  return new Blob(dataAsBytes);
            }

            return new BlobFromLocator(this, columnIndex);
      }

      public static boolean arraysEqual(byte[] left, byte[] right) {
            if (left == null) {
                  return right == null;
            }
            if (right == null) {
                  return false;
            }
            if (left.length != right.length) {
                  return false;
            }
            for (int i = 0; i < left.length; i++) {
                  if (left[i] != right[i]) {
                        return false;
                  }
            }
            return true;
      }

      /**
       * Get the value of a column in the current row as a Java byte.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
03227       protected byte getNativeByte(int columnIndex) throws SQLException {
            return getNativeByte(columnIndex, true);
      }
      
      protected byte getNativeByte(int columnIndex, boolean overflowCheck) throws SQLException {
            checkRowPos();

            checkColumnBounds(columnIndex);

            Object value = this.thisRow.getColumnValue(columnIndex - 1);
            
            if (value == null) {
                  this.wasNullFlag = true;

                  return 0;
            }

            if (value == null) {
                  this.wasNullFlag = true;
            } else {
                  this.wasNullFlag = false;
            }
                  
            if (this.wasNullFlag) {
                  return 0;
            }

            columnIndex--;

            Field field = this.fields[columnIndex];

            switch (field.getMysqlType()) {
            case MysqlDefs.FIELD_TYPE_BIT:
                  long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads &&
                              (valueAsLong < Byte.MIN_VALUE
                                          || valueAsLong > Byte.MAX_VALUE)) {
                        throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
                                    Types.TINYINT);
                  }
                  
                  return (byte)valueAsLong;
            case MysqlDefs.FIELD_TYPE_TINY:
                  byte valueAsByte = ((byte[]) value)[0];
                  
                  if (!field.isUnsigned()) {
                        return valueAsByte;
                  }

                  short valueAsShort = (valueAsByte >= 0) ? 
                              valueAsByte : (short)(valueAsByte + (short)256);
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsShort > Byte.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsShort),
                                          columnIndex + 1, Types.TINYINT);
                        }
                  }
                  
                  return (byte)valueAsShort;

            case MysqlDefs.FIELD_TYPE_SHORT:
            case MysqlDefs.FIELD_TYPE_YEAR:
                  valueAsShort = getNativeShort(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsShort < Byte.MIN_VALUE
                                    || valueAsShort > Byte.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsShort),
                                          columnIndex + 1, Types.TINYINT);
                        }
                  }

                  return (byte) valueAsShort;
            case MysqlDefs.FIELD_TYPE_INT24:
            case MysqlDefs.FIELD_TYPE_LONG:
                  int valueAsInt = getNativeInt(columnIndex + 1, false);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsInt < Byte.MIN_VALUE || valueAsInt > Byte.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsInt),
                                          columnIndex + 1, Types.TINYINT);
                        }
                  }

                  return (byte) valueAsInt;

            case MysqlDefs.FIELD_TYPE_FLOAT:
                  float valueAsFloat = getNativeFloat(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsFloat < Byte.MIN_VALUE
                                    || valueAsFloat > Byte.MAX_VALUE) {

                              throwRangeException(String.valueOf(valueAsFloat),
                                          columnIndex + 1, Types.TINYINT);
                        }
                  }

                  return (byte) valueAsFloat;

            case MysqlDefs.FIELD_TYPE_DOUBLE:
                  double valueAsDouble = getNativeDouble(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsDouble < Byte.MIN_VALUE
                                    || valueAsDouble > Byte.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsDouble),
                                          columnIndex + 1, Types.TINYINT);
                        }
                  }

                  return (byte) valueAsDouble;

            case MysqlDefs.FIELD_TYPE_LONGLONG:
                  valueAsLong = getNativeLong(columnIndex + 1, false, true);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsLong < Byte.MIN_VALUE
                                    || valueAsLong > Byte.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsLong),
                                          columnIndex + 1, Types.TINYINT);
                        }
                  }

                  return (byte) valueAsLong;

            default:
                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getByte()", columnIndex,
                                    this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex],
                                    new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }

                  return getByteFromString(getNativeString(columnIndex + 1),
                              columnIndex + 1);
            }
      }

      /**
       * Get the value of a column in the current row as a Java byte array.
       * 
       * <p>
       * <b>Be warned</b> If the blob is huge, then you may run out of memory.
       * </p>
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
03387       protected byte[] getNativeBytes(int columnIndex, boolean noConversion)
                  throws SQLException {
            checkRowPos();

            checkColumnBounds(columnIndex);

            Object value = this.thisRow.getColumnValue(columnIndex - 1);
            
            if (value == null) {
                  this.wasNullFlag = true;
            } else {
                  this.wasNullFlag = false;
            }

            if (this.wasNullFlag) {
                  return null;
            }

            Field field = this.fields[columnIndex - 1];
            
            int mysqlType = field.getMysqlType();

            // Workaround for emulated locators in servers > 4.1,
            // as server returns SUBSTRING(blob) as STRING type...
            if (noConversion) {
                  mysqlType = MysqlDefs.FIELD_TYPE_BLOB;
            }

            switch (mysqlType) {
            case MysqlDefs.FIELD_TYPE_TINY_BLOB:
            case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
            case MysqlDefs.FIELD_TYPE_LONG_BLOB:
            case MysqlDefs.FIELD_TYPE_BLOB:
            case MysqlDefs.FIELD_TYPE_BIT:
                  return (byte[]) value;

            default:
                  int sqlType = field.getSQLType();
            
                  if (sqlType == Types.VARBINARY || sqlType == Types.BINARY) {
                        return (byte[]) value;
                  }
            
                  return getBytesFromString(getNativeString(columnIndex), columnIndex);
            }
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Get the value of a column in the current row as a java.io.Reader.
       * </p>
       * 
       * @param columnIndex
       *            the column to get the value from
       * 
       * @return the value in the column as a java.io.Reader.
       * 
       * @throws SQLException
       *             if an error occurs
       */
03449       protected java.io.Reader getNativeCharacterStream(int columnIndex)
                  throws SQLException {
            int columnIndexMinusOne = columnIndex - 1;
            
            switch (this.fields[columnIndexMinusOne].getSQLType()) {
            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
            case Types.CLOB:        
                  if (this.thisRow.isNull(columnIndexMinusOne)) {
                        this.wasNullFlag = true;
                        
                        return null;
                  }
                  
                  this.wasNullFlag = false;
                  
                  return this.thisRow.getReader(columnIndexMinusOne);
            }
            
            String asString = null;
            
            asString = getStringForClob(columnIndex);

            if (asString == null) {
                  return null;
            }
            
            return getCharacterStreamFromString(asString, columnIndex);
      }

      /**
       * JDBC 2.0 Get a CLOB column.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing a CLOB
       * 
       * @throws SQLException
       *             if an error occurs
       */
03491       protected java.sql.Clob getNativeClob(int columnIndex) throws SQLException {
            String stringVal = getStringForClob(columnIndex);

            if (stringVal == null) {
                  return null;
            }

            return getClobFromString(stringVal, columnIndex);
      }

      private String getNativeConvertToString(int columnIndex, 
                  Field field)
                  throws SQLException {

            
            int sqlType = field.getSQLType();
            int mysqlType = field.getMysqlType();

            switch (sqlType) {
            case Types.BIT:
                  return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
            case Types.BOOLEAN:
                  boolean booleanVal = getBoolean(columnIndex);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  return String.valueOf(booleanVal);

            case Types.TINYINT:
                  byte tinyintVal = getNativeByte(columnIndex, false);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  if (!field.isUnsigned() || tinyintVal >= 0) {
                        return String.valueOf(tinyintVal);
                  }

                  short unsignedTinyVal = (short) (tinyintVal & 0xff);

                  return String.valueOf(unsignedTinyVal);

            case Types.SMALLINT:

                  int intVal = getNativeInt(columnIndex, false);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  if (!field.isUnsigned() || intVal >= 0) {
                        return String.valueOf(intVal);
                  }

                  intVal = intVal & 0xffff;

                  return String.valueOf(intVal);

            case Types.INTEGER:
                  intVal = getNativeInt(columnIndex, false);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  if (!field.isUnsigned() || intVal >= 0
                              || field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {

                        return String.valueOf(intVal);
                  }

                  long longVal = intVal & 0xffffffffL;

                  return String.valueOf(longVal);

            case Types.BIGINT:

                  if (!field.isUnsigned()) {
                        longVal = getNativeLong(columnIndex, false, true);

                        if (this.wasNullFlag) {
                              return null;
                        }

                        return String.valueOf(longVal);
                  }

                  longVal = getNativeLong(columnIndex, false, false);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  return String.valueOf(convertLongToUlong(longVal));
            case Types.REAL:
                  float floatVal = getNativeFloat(columnIndex);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  return String.valueOf(floatVal);

            case Types.FLOAT:
            case Types.DOUBLE:
                  double doubleVal = getNativeDouble(columnIndex);

                  if (this.wasNullFlag) {
                        return null;
                  }

                  return String.valueOf(doubleVal);

            case Types.DECIMAL:
            case Types.NUMERIC:
                  String stringVal = StringUtils
                              .toAsciiString((byte[]) this.thisRow.getColumnValue(columnIndex - 1));

                  BigDecimal val;

                  if (stringVal != null) {
                        this.wasNullFlag = false;
                        
                        if (stringVal.length() == 0) {
                              val = new BigDecimal(0);

                              return val.toString();
                        }

                        try {
                              val = new BigDecimal(stringVal);
                        } catch (NumberFormatException ex) {
                              throw SQLError.createSQLException(
                                          Messages
                                                      .getString("ResultSet.Bad_format_for_BigDecimal", 
                                                                  new Object[] {stringVal, Constants.integerValueOf(columnIndex)}),
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        }

                        return val.toString();
                  }

                  this.wasNullFlag = true;
                  
                  return null;

            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:

                  return extractStringFromNativeColumn(columnIndex, mysqlType);
            case Types.BINARY:
            case Types.VARBINARY:
            case Types.LONGVARBINARY:

                  if (!field.isBlob()) {
                        return extractStringFromNativeColumn(columnIndex, mysqlType);
                  } else if (!field.isBinary()) {
                        return extractStringFromNativeColumn(columnIndex, mysqlType);
                  } else {
                        byte[] data = getBytes(columnIndex);
                        Object obj = data;

                        if ((data != null) && (data.length >= 2)) {
                              if ((data[0] == -84) && (data[1] == -19)) {
                                    // Serialized object?
                                    try {
                                          ByteArrayInputStream bytesIn = new ByteArrayInputStream(
                                                      data);
                                          ObjectInputStream objIn = new ObjectInputStream(
                                                      bytesIn);
                                          obj = objIn.readObject();
                                          objIn.close();
                                          bytesIn.close();
                                    } catch (ClassNotFoundException cnfe) {
                                          throw SQLError.createSQLException(
                                                      Messages
                                                                  .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
                                                                  + cnfe.toString()
                                                                  + Messages
                                                                              .getString("ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$
                                    } catch (IOException ex) {
                                          obj = data; // not serialized?
                                    }
                              }

                              return obj.toString();
                        }

                        return extractStringFromNativeColumn(columnIndex, mysqlType);
                  }

            case Types.DATE:

                  // The YEAR datatype needs to be handled differently here.
                  if (mysqlType == MysqlDefs.FIELD_TYPE_YEAR) {
                        short shortVal = getNativeShort(columnIndex);

                        if (!this.connection.getYearIsDateType()) {

                              if (this.wasNullFlag) {
                                    return null;
                              }

                              return String.valueOf(shortVal);
                        }

                        if (field.getLength() == 2) {

                              if (shortVal <= 69) {
                                    shortVal = (short) (shortVal + 100);
                              }

                              shortVal += 1900;
                        }

                        return fastDateCreate(null, shortVal, 1, 1).toString();

                  }

                  Date dt = getNativeDate(columnIndex);

                  if (dt == null) {
                        return null;
                  }

                  return String.valueOf(dt);

            case Types.TIME:
                  Time tm = getNativeTime(columnIndex, null, this.defaultTimeZone, false);

                  if (tm == null) {
                        return null;
                  }

                  return String.valueOf(tm);

            case Types.TIMESTAMP:
                  Timestamp tstamp = getNativeTimestamp(columnIndex,
                              null, this.defaultTimeZone, false);

                  if (tstamp == null) {
                        return null;
                  }

                  String result = String.valueOf(tstamp);

                  if (!this.connection.getNoDatetimeStringSync()) {
                        return result;
                  }

                  if (result.endsWith(".0")) {
                        return result.substring(0, result.length() - 2);
                  }

            default:
                  return extractStringFromNativeColumn(columnIndex, mysqlType);
            }
      }

      /**
       * Get the value of a column in the current row as a java.sql.Date object
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value; null if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
03765       protected java.sql.Date getNativeDate(int columnIndex) throws SQLException {
            return getNativeDate(columnIndex, null);
      }

      /**
       * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
       * object. Use the calendar to construct an appropriate millisecond value
       * for the Date, if the underlying database doesn't store timezone
       * information.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param tz
       *            the calendar to use in constructing the date
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
03785       protected java.sql.Date getNativeDate(int columnIndex, TimeZone tz)
                  throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            int columnIndexMinusOne = columnIndex - 1;
            
            int mysqlType = this.fields[columnIndexMinusOne].getMysqlType();
            
            java.sql.Date dateToReturn = null;
            
            if (mysqlType == MysqlDefs.FIELD_TYPE_DATE) {

                  dateToReturn = this.thisRow.getNativeDate(columnIndexMinusOne, 
                              this.connection, this); 
            } else {

                  boolean rollForward = (tz != null && !tz.equals(this.getDefaultTimeZone()));
                  
                  dateToReturn = (Date) this.thisRow.getNativeDateTimeValue(columnIndexMinusOne,
                              null, Types.DATE, mysqlType, tz, rollForward, this.connection,
                              this);
            }
            
            //
            // normally, we allow ResultSetImpl methods to check for null first,
            // but with DATETIME values we have this wacky need to support
            // 0000-00-00 00:00:00 -> NULL, so we have to defer
            // to the RowHolder implementation, and check the return value.
            //

            if (dateToReturn == null) {

                  this.wasNullFlag = true;

                  return null;
            }

            this.wasNullFlag = false;

            return dateToReturn;
      }

      java.sql.Date getNativeDateViaParseConversion(int columnIndex) throws SQLException {
            if (this.useUsageAdvisor) {
                  issueConversionViaParsingWarning("getDate()", columnIndex,
                              this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1],
                              new int[] { MysqlDefs.FIELD_TYPE_DATE });
            }

            String stringVal = getNativeString(columnIndex);

            return getDateFromString(stringVal, columnIndex);
      }

      /**
       * Get the value of a column in the current row as a Java double.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
03851       protected double getNativeDouble(int columnIndex) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            columnIndex--; // / JDBC is 1-based

            if (this.thisRow.isNull(columnIndex)) {
                  this.wasNullFlag = true;

                  return 0;
            }

            this.wasNullFlag = false;

            Field f= this.fields[columnIndex];
            
            switch (f.getMysqlType()) {
            case MysqlDefs.FIELD_TYPE_DOUBLE:
                  return this.thisRow.getNativeDouble(columnIndex);
            case MysqlDefs.FIELD_TYPE_TINY:
                  if (!f.isUnsigned()) {
                        return (double) getNativeByte(columnIndex + 1);
                  }
                  
                  return (double) getNativeShort(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_SHORT:
            case MysqlDefs.FIELD_TYPE_YEAR:
                  if (!f.isUnsigned()) {
                        return (double) getNativeShort(columnIndex + 1);
                  }
                  
                  return (double) getNativeInt(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_INT24:
            case MysqlDefs.FIELD_TYPE_LONG:
                  if (!f.isUnsigned()) {
                        return (double) getNativeInt(columnIndex + 1);
                  }
                  
                  return (double) getNativeLong(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_LONGLONG:
                  long valueAsLong = getNativeLong(columnIndex + 1);
                  
                  if (!f.isUnsigned()) {
                        return (double) valueAsLong;
                  }
                  
                  BigInteger asBigInt = convertLongToUlong(valueAsLong);
                  
                  // TODO: Check for overflow
                  
                  return asBigInt.doubleValue();
            case MysqlDefs.FIELD_TYPE_FLOAT:
                  return (double) getNativeFloat(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_BIT:
                  return getNumericRepresentationOfSQLBitType(columnIndex + 1);
            default:
                  String stringVal = getNativeString(columnIndex + 1);

                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getDouble()", columnIndex,
                                    stringVal, this.fields[columnIndex],
                                    new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }

                  return getDoubleFromString(stringVal, columnIndex + 1);
            }
      }

      /**
       * Get the value of a column in the current row as a Java float.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
03935       protected float getNativeFloat(int columnIndex) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            columnIndex--; // / JDBC is 1-based

            if (this.thisRow.isNull(columnIndex)) {
                  this.wasNullFlag = true;

                  return 0;
            }

            this.wasNullFlag = false;

            Field f = this.fields[columnIndex];
            
            switch (f.getMysqlType()) {
            case MysqlDefs.FIELD_TYPE_BIT:
                  long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);

                  return valueAsLong;
            case MysqlDefs.FIELD_TYPE_DOUBLE:
                  
                  // Only foolproof way to check for overflow
                  // Not efficient, but if you don't want to be inefficient, use the
                  // correct binding for the type!
                  
                  Double valueAsDouble = new Double(getNativeDouble(columnIndex + 1));
                  
                  float valueAsFloat = valueAsDouble.floatValue();
                  
                  if (this.jdbcCompliantTruncationForReads && 
                              valueAsFloat == Float.NEGATIVE_INFINITY ||
                              valueAsFloat == Float.POSITIVE_INFINITY) {
                        throwRangeException(valueAsDouble.toString(), 
                                    columnIndex + 1, Types.FLOAT);
                  }

                  return (float) getNativeDouble(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_TINY:
                  if (!f.isUnsigned()) {
                        return (float) getNativeByte(columnIndex + 1);
                  }
                  
                  return (float) getNativeShort(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_SHORT:
            case MysqlDefs.FIELD_TYPE_YEAR:
                  if (!f.isUnsigned()) {
                        return (float) getNativeShort(columnIndex + 1);
                  }
                  
                  return (float) getNativeInt(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_INT24:
            case MysqlDefs.FIELD_TYPE_LONG:
                  if (!f.isUnsigned()) {
                        return (float) getNativeInt(columnIndex + 1);
                  }
                  
                  return (float) getNativeLong(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_LONGLONG:
                  valueAsLong = getNativeLong(columnIndex + 1);
                  
                  if (!f.isUnsigned()) {
                        return (float) valueAsLong;
                  }
                  
                  BigInteger asBigInt = convertLongToUlong(valueAsLong);
                  
                  // TODO: Check for overflow
                  
                  return asBigInt.floatValue();
            case MysqlDefs.FIELD_TYPE_FLOAT:
                  
                  return this.thisRow.getNativeFloat(columnIndex);

            default:
                  String stringVal = getNativeString(columnIndex + 1);
            
                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getFloat()", columnIndex,
                                    stringVal, this.fields[columnIndex],
                                    new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }

                  return getFloatFromString(stringVal, columnIndex + 1);
            }
      }

      /**
       * Get the value of a column in the current row as a Java int.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
04039       protected int getNativeInt(int columnIndex) throws SQLException {
            return getNativeInt(columnIndex, true);
      }
      
      protected int getNativeInt(int columnIndex, boolean overflowCheck) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            columnIndex--; // / JDBC is 1-based

            if (this.thisRow.isNull(columnIndex)) {
                  this.wasNullFlag = true;

                  return 0;
            }

            this.wasNullFlag = false;

            Field f = this.fields[columnIndex];

            switch (f.getMysqlType()) {
            case MysqlDefs.FIELD_TYPE_BIT:
                  long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads &&
                              (valueAsLong < Integer.MIN_VALUE
                                          || valueAsLong > Integer.MAX_VALUE)) {
                        throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
                                    Types.INTEGER);
                  }
                  
                  return (short)valueAsLong;
            case MysqlDefs.FIELD_TYPE_TINY:
                  byte tinyintVal = getNativeByte(columnIndex + 1, false);
                  
                  if (!f.isUnsigned() || tinyintVal >= 0) {
                        return tinyintVal;
                  }

                  return tinyintVal + 256;
            case MysqlDefs.FIELD_TYPE_SHORT:
            case MysqlDefs.FIELD_TYPE_YEAR:
                  short asShort = getNativeShort(columnIndex + 1, false);
                  
                  if (!f.isUnsigned() || asShort >= 0) {
                        return asShort;
                  }

                  return asShort + 65536;
            case MysqlDefs.FIELD_TYPE_INT24:
            case MysqlDefs.FIELD_TYPE_LONG:
                  
                  int valueAsInt = this.thisRow.getNativeInt(columnIndex);

                  if (!f.isUnsigned()) {  
                        return valueAsInt;
                  }
                  
                  valueAsLong = (valueAsInt >= 0) ? 
                              valueAsInt : valueAsInt + 4294967296L; 
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads &&
                              valueAsLong > Integer.MAX_VALUE) {
                        throwRangeException(String.valueOf(valueAsLong),
                                    columnIndex + 1, Types.INTEGER);
                  }
                  
                  return (int)valueAsLong;
            case MysqlDefs.FIELD_TYPE_LONGLONG:
                  valueAsLong = getNativeLong(columnIndex + 1, false, true);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsLong < Integer.MIN_VALUE
                                    || valueAsLong > Integer.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsLong),
                                          columnIndex + 1, Types.INTEGER);
                        }
                  }

                  return (int) valueAsLong;
            case MysqlDefs.FIELD_TYPE_DOUBLE:
                  double valueAsDouble = getNativeDouble(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsDouble < Integer.MIN_VALUE
                                    || valueAsDouble > Integer.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsDouble),
                                          columnIndex + 1, Types.INTEGER);
                        }
                  }

                  return (int) valueAsDouble;
            case MysqlDefs.FIELD_TYPE_FLOAT:
                  valueAsDouble = getNativeFloat(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsDouble < Integer.MIN_VALUE
                                    || valueAsDouble > Integer.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsDouble),
                                          columnIndex + 1, Types.INTEGER);
                        }
                  }

                  return (int) valueAsDouble;

            default:
                  String stringVal = getNativeString(columnIndex + 1);
            
                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getInt()", columnIndex,
                                    stringVal, this.fields[columnIndex],
                                    new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }

                  return getIntFromString(stringVal, columnIndex + 1);
            }
      }

      /**
       * Get the value of a column in the current row as a Java long.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
04173       protected long getNativeLong(int columnIndex) throws SQLException {
            return getNativeLong(columnIndex, true, true);
      }
      
      protected long getNativeLong(int columnIndex, boolean overflowCheck, 
                  boolean expandUnsignedLong) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            columnIndex--; // / JDBC is 1-based

            if (this.thisRow.isNull(columnIndex)) {
                  this.wasNullFlag = true;

                  return 0;
            }

            this.wasNullFlag = false;

            Field f = this.fields[columnIndex];

            switch (f.getMysqlType()) {
            case MysqlDefs.FIELD_TYPE_BIT:
                  return getNumericRepresentationOfSQLBitType(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_TINY:
                  if (!f.isUnsigned()) {
                        return getNativeByte(columnIndex + 1);
                  }

                  return getNativeInt(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_SHORT:
                  if (!f.isUnsigned()) {
                        return getNativeShort(columnIndex + 1);
                  }

                  return getNativeInt(columnIndex + 1, false);
            case MysqlDefs.FIELD_TYPE_YEAR:

                  return getNativeShort(columnIndex + 1);
            case MysqlDefs.FIELD_TYPE_INT24:
            case MysqlDefs.FIELD_TYPE_LONG:
                  int asInt = getNativeInt(columnIndex + 1, false);
                  
                  if (!f.isUnsigned() || asInt >= 0) {
                        return asInt;
                  }

                  return asInt + 4294967296L;
            case MysqlDefs.FIELD_TYPE_LONGLONG:
                  long valueAsLong = this.thisRow.getNativeLong(columnIndex);

                  if (!f.isUnsigned() || !expandUnsignedLong) {
                        return valueAsLong;
                  }
                  
                  BigInteger asBigInt = convertLongToUlong(valueAsLong);
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads && 
                              ((asBigInt.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0 ) ||
                               (asBigInt.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0))) {
                        throwRangeException(asBigInt.toString(),
                                    columnIndex + 1, Types.BIGINT);
                  }
                  
                  return getLongFromString(asBigInt.toString(), columnIndex + 1);

            case MysqlDefs.FIELD_TYPE_DOUBLE:
                  double valueAsDouble = getNativeDouble(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsDouble < Long.MIN_VALUE
                                    || valueAsDouble > Long.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsDouble),
                                          columnIndex + 1, Types.BIGINT);
                        }
                  }

                  return (long) valueAsDouble;
            case MysqlDefs.FIELD_TYPE_FLOAT:
                  valueAsDouble = getNativeFloat(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsDouble < Long.MIN_VALUE
                                    || valueAsDouble > Long.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsDouble),
                                          columnIndex + 1, Types.BIGINT);
                        }
                  }

                  return (long) valueAsDouble;
            default:
                  String stringVal = getNativeString(columnIndex + 1);
            
                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getLong()", columnIndex,
                                    stringVal, this.fields[columnIndex],
                                    new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }

                  return getLongFromString(stringVal, columnIndex + 1);
            }
      }

      /**
       * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
       * 
       * @param i
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing data of an SQL REF type
       * 
       * @throws SQLException
       *             as this is not implemented
       * @throws NotImplemented
       *             DOCUMENT ME!
       */
04294       protected java.sql.Ref getNativeRef(int i) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * Get the value of a column in the current row as a Java short.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
04309       protected short getNativeShort(int columnIndex) throws SQLException {
            return getNativeShort(columnIndex, true);
      }
      
      protected short getNativeShort(int columnIndex, boolean overflowCheck) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            columnIndex--; // / JDBC is 1-based

            
            if (this.thisRow.isNull(columnIndex)) {
                  this.wasNullFlag = true;

                  return 0;
            }

            this.wasNullFlag = false;

            Field f = this.fields[columnIndex];

            switch (f.getMysqlType()) {

            case MysqlDefs.FIELD_TYPE_TINY:
                  byte tinyintVal = getNativeByte(columnIndex + 1, false);
                  
                  if (!f.isUnsigned() || tinyintVal >= 0) {
                  return tinyintVal;
                  }
                  
                  return (short)(tinyintVal + (short)256);
            case MysqlDefs.FIELD_TYPE_SHORT:
            case MysqlDefs.FIELD_TYPE_YEAR:
                  
                  short asShort = this.thisRow.getNativeShort(columnIndex);

                  if (!f.isUnsigned()) {
                        return asShort;
                  }
                  
                  int valueAsInt = asShort & 0xffff;
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads &&
                              valueAsInt > Short.MAX_VALUE) {
                        throwRangeException(String.valueOf(valueAsInt),
                                    columnIndex + 1, Types.SMALLINT);
                  }
                  
                  return (short)valueAsInt;
            case MysqlDefs.FIELD_TYPE_INT24:
            case MysqlDefs.FIELD_TYPE_LONG:
                  if (!f.isUnsigned()) {
                        valueAsInt = getNativeInt(columnIndex + 1, false);
                        
                        if (overflowCheck && this.jdbcCompliantTruncationForReads &&
                                    valueAsInt > Short.MAX_VALUE ||
                                    valueAsInt < Short.MIN_VALUE) {
                              throwRangeException(String.valueOf(valueAsInt),
                                          columnIndex + 1, Types.SMALLINT);
                        }
                        
                        return (short)valueAsInt;
                  }
                  
                  long valueAsLong = getNativeLong(columnIndex + 1, false, true);
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads &&
                              valueAsLong > Short.MAX_VALUE) {
                        throwRangeException(String.valueOf(valueAsLong),
                                    columnIndex + 1, Types.SMALLINT);
                  }
                  
                  return (short)valueAsLong;
                  
            case MysqlDefs.FIELD_TYPE_LONGLONG:
                  valueAsLong = getNativeLong(columnIndex + 1, false, false);
                  
                  if (!f.isUnsigned()) {
                        if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                              if (valueAsLong < Short.MIN_VALUE
                                          || valueAsLong > Short.MAX_VALUE) {
                                    throwRangeException(String.valueOf(valueAsLong),
                                                columnIndex + 1, Types.SMALLINT);
                              }
                        }
      
                        return (short) valueAsLong;
                  }
                  
                  BigInteger asBigInt = convertLongToUlong(valueAsLong);
                  
                  if (overflowCheck && this.jdbcCompliantTruncationForReads && 
                              ((asBigInt.compareTo(new BigInteger(String.valueOf(Short.MAX_VALUE))) > 0 ) ||
                               (asBigInt.compareTo(new BigInteger(String.valueOf(Short.MIN_VALUE))) < 0))) {
                        throwRangeException(asBigInt.toString(),
                                    columnIndex + 1, Types.SMALLINT);
                  }
                  
                  return (short)getIntFromString(asBigInt.toString(), columnIndex + 1);

            case MysqlDefs.FIELD_TYPE_DOUBLE:
                  double valueAsDouble = getNativeDouble(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsDouble < Short.MIN_VALUE
                                    || valueAsDouble > Short.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsDouble),
                                          columnIndex + 1, Types.SMALLINT);
                        }
                  }

                  return (short) valueAsDouble;
            case MysqlDefs.FIELD_TYPE_FLOAT:
                  float valueAsFloat = getNativeFloat(columnIndex + 1);

                  if (overflowCheck && this.jdbcCompliantTruncationForReads) {
                        if (valueAsFloat < Short.MIN_VALUE
                                    || valueAsFloat > Short.MAX_VALUE) {
                              throwRangeException(String.valueOf(valueAsFloat),
                                          columnIndex + 1, Types.SMALLINT);
                        }
                  }

                  return (short) valueAsFloat;
            default:
                  String stringVal = getNativeString(columnIndex + 1);
            
                  if (this.useUsageAdvisor) {
                        issueConversionViaParsingWarning("getShort()", columnIndex,
                                    stringVal, this.fields[columnIndex],
                                    new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
                                                MysqlDefs.FIELD_TYPE_TINY,
                                                MysqlDefs.FIELD_TYPE_SHORT,
                                                MysqlDefs.FIELD_TYPE_LONG,
                                                MysqlDefs.FIELD_TYPE_LONGLONG,
                                                MysqlDefs.FIELD_TYPE_FLOAT });
                  }

                  return getShortFromString(stringVal, columnIndex + 1);
            }
      }

      /**
       * Get the value of a column in the current row as a Java String
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value, null for SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
04462       protected String getNativeString(int columnIndex) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            if (this.fields == null) {
                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Query_generated_no_fields_for_ResultSet_133"), //$NON-NLS-1$
                              SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
            }
            
            if (this.thisRow.isNull(columnIndex - 1)) {
                  this.wasNullFlag = true;

                  return null;
            }

            this.wasNullFlag = false;

            String stringVal = null;

            Field field = this.fields[columnIndex - 1];

            // TODO: Check Types Here.
            stringVal = getNativeConvertToString(columnIndex, field);

            if (field.isZeroFill() && (stringVal != null)) {
                  int origLength = stringVal.length();

                  StringBuffer zeroFillBuf = new StringBuffer(origLength);

                  long numZeros = field.getLength() - origLength;

                  for (long i = 0; i < numZeros; i++) {
                        zeroFillBuf.append('0');
                  }

                  zeroFillBuf.append(stringVal);

                  stringVal = zeroFillBuf.toString();
            }

            return stringVal;
      }

      private Time getNativeTime(int columnIndex, Calendar targetCalendar,
                  TimeZone tz, boolean rollForward)
                  throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            int columnIndexMinusOne = columnIndex - 1;
            
            int mysqlType = this.fields[columnIndexMinusOne].getMysqlType();

            Time timeVal = null;
            
            if (mysqlType == MysqlDefs.FIELD_TYPE_TIME) {
                  timeVal = this.thisRow.getNativeTime(columnIndexMinusOne, 
                              targetCalendar, tz, rollForward, this.connection, this);
                  
            } else {
                  timeVal = (Time) this.thisRow.getNativeDateTimeValue(columnIndexMinusOne,
                              null, Types.TIME, mysqlType, tz, rollForward, this.connection,
                              this);
            }
            
            //
            // normally, we allow ResultSetImpl methods to check for null first,
            // but with DATETIME values we have this wacky need to support
            // 0000-00-00 00:00:00 -> NULL, so we have to defer
            // to the RowHolder implementation, and check the return value.
            //

            if (timeVal == null) {

                  this.wasNullFlag = true;

                  return null;
            }

            this.wasNullFlag = false;

            return timeVal;
      }
      
      Time getNativeTimeViaParseConversion(int columnIndex, Calendar targetCalendar,
                  TimeZone tz, boolean rollForward) throws SQLException {
            if (this.useUsageAdvisor) {
                  issueConversionViaParsingWarning("getTime()", columnIndex,
                              this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1],
                              new int[] { MysqlDefs.FIELD_TYPE_TIME });
            }
      
            String strTime = getNativeString(columnIndex);
      
            return getTimeFromString(strTime, targetCalendar, columnIndex, tz, rollForward);
      }

      private Timestamp getNativeTimestamp(int columnIndex, 
                  Calendar targetCalendar,
                  TimeZone tz,
                  boolean rollForward) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            int columnIndexMinusOne = columnIndex - 1;
            
            Timestamp tsVal = null;

            int mysqlType = this.fields[columnIndexMinusOne].getMysqlType();

            switch (mysqlType) {
            case MysqlDefs.FIELD_TYPE_DATETIME:
            case MysqlDefs.FIELD_TYPE_TIMESTAMP:
                  tsVal = this.thisRow.getNativeTimestamp(columnIndexMinusOne,
                              targetCalendar, tz, rollForward, this.connection, this);
                  break;

            default:
                  

                  tsVal = (Timestamp) this.thisRow.getNativeDateTimeValue(
                              columnIndexMinusOne, null, Types.TIMESTAMP, mysqlType, tz,
                              rollForward, this.connection, this);
            }

            //
            // normally, we allow ResultSetImpl methods to check for null first,
            // but with DATETIME values we have this wacky need to support
            // 0000-00-00 00:00:00 -> NULL, so we have to defer
            // to the RowHolder implementation, and check the return value.
            //
            
            if (tsVal == null) {

                  this.wasNullFlag = true;

                  return null;
            }

            this.wasNullFlag = false;

            return tsVal;
      }

      Timestamp getNativeTimestampViaParseConversion(int columnIndex, Calendar targetCalendar, 
                  TimeZone tz, boolean rollForward) throws SQLException {
            if (this.useUsageAdvisor) {
                  issueConversionViaParsingWarning("getTimestamp()", columnIndex,
                              this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1],
                              new int[] { MysqlDefs.FIELD_TYPE_TIMESTAMP,
                                          MysqlDefs.FIELD_TYPE_DATETIME });
            }

            String strTimestamp = getNativeString(columnIndex);

            return getTimestampFromString(columnIndex, targetCalendar, strTimestamp, tz,
                        rollForward);
      }

      // ---------------------------------------------------------------------
      // Updates
      // ---------------------------------------------------------------------

      /**
       * A column value can also be retrieved as a stream of Unicode characters.
       * We implement this as a binary stream.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return a Java InputStream that delivers the database column value as a
       *         stream of two byte Unicode characters. If the value is SQL NULL,
       *         then the result is null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @see getAsciiStream
       * @see getBinaryStream
       */
04644       protected InputStream getNativeUnicodeStream(int columnIndex)
                  throws SQLException {
            checkRowPos();

            return getBinaryStream(columnIndex);
      }

      /**
       * @see ResultSetInternalMethods#getURL(int)
       */
04654       protected URL getNativeURL(int colIndex) throws SQLException {
            String val = getString(colIndex);

            if (val == null) {
                  return null;
            }

            try {
                  return new URL(val);
            } catch (MalformedURLException mfe) {
                  throw SQLError.createSQLException(Messages
                              .getString("ResultSet.Malformed_URL____141")
                              + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * DOCUMENT ME!
       * 
       * @return Returns the nextResultSet, if any, null if none exists.
       */
04675       public ResultSetInternalMethods getNextResultSet() {
            return this.nextResultSet;
      }

      /**
       * Get the value of a column in the current row as a Java object
       * 
       * <p>
       * This method will return the value of the given column as a Java object.
       * The type of the Java object will be the default Java Object type
       * corresponding to the column's SQL type, following the mapping specified
       * in the JDBC specification.
       * </p>
       * 
       * <p>
       * This method may also be used to read database specific abstract data
       * types.
       * </p>
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return a Object holding the column value
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
04702       public Object getObject(int columnIndex) throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);
            
            int columnIndexMinusOne = columnIndex - 1;
            
            if (this.thisRow.isNull(columnIndexMinusOne)) {
                  this.wasNullFlag = true;

                  return null;
            }
            
            this.wasNullFlag = false;

            Field field;
            field = this.fields[columnIndexMinusOne];

            switch (field.getSQLType()) {
            case Types.BIT:
            case Types.BOOLEAN:
                  if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT
                              && !field.isSingleBit()) {
                        return getBytes(columnIndex);
                  }

                  // valueOf would be nicer here, but it isn't
                  // present in JDK-1.3.1, which is what the CTS
                  // uses.
                  return Boolean.valueOf(getBoolean(columnIndex));

            case Types.TINYINT:
                  if (!field.isUnsigned()) {
                        return Constants.integerValueOf(getByte(columnIndex));
                  }

                  return Constants.integerValueOf(getInt(columnIndex));

            case Types.SMALLINT:

                  return Constants.integerValueOf(getInt(columnIndex));

            case Types.INTEGER:

                  if (!field.isUnsigned() || 
                              field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
                        return Constants.integerValueOf(getInt(columnIndex));
                  }

                  return Constants.longValueOf(getLong(columnIndex));
                  
            case Types.BIGINT:

                  if (!field.isUnsigned()) {
                        return Constants.longValueOf(getLong(columnIndex));
                  }

                  String stringVal = getString(columnIndex);

                  if (stringVal == null) {
                        return null;
                  }

                  try {
                        return new BigInteger(stringVal);
                  } catch (NumberFormatException nfe) {
                        throw SQLError.createSQLException(Messages.getString(
                                    "ResultSet.Bad_format_for_BigInteger", new Object[] {
                                                Constants.integerValueOf(columnIndex), stringVal }),
                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
                  }

            case Types.DECIMAL:
            case Types.NUMERIC:
                  stringVal = getString(columnIndex);

                  BigDecimal val;

                  if (stringVal != null) {
                        if (stringVal.length() == 0) {
                              val = new BigDecimal(0);

                              return val;
                        }

                        try {
                              val = new BigDecimal(stringVal);
                        } catch (NumberFormatException ex) {
                              throw SQLError.createSQLException(
                                          Messages
                                                      .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
                                                      + stringVal
                                                      + Messages
                                                                  .getString("ResultSet.___in_column__87")
                                                      + columnIndex + "(" //$NON-NLS-1$
                                                      + this.fields[columnIndex - 1] + ").",
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        }

                        return val;
                  }

                  return null;

            case Types.REAL:
                  return new Float(getFloat(columnIndex));

            case Types.FLOAT:
            case Types.DOUBLE:
                  return new Double(getDouble(columnIndex));

            case Types.CHAR:
            case Types.VARCHAR:
                  if (!field.isOpaqueBinary()) {
                        return getString(columnIndex);
                  }

                  return getBytes(columnIndex);
            case Types.LONGVARCHAR:
                  if (!field.isOpaqueBinary()) {
                        return getStringForClob(columnIndex);
                  }

                  return getBytes(columnIndex);

            case Types.BINARY:
            case Types.VARBINARY:
            case Types.LONGVARBINARY:
                  if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_GEOMETRY) {
                        return getBytes(columnIndex);
                  } else if (field.isBinary() || field.isBlob()) {
                        byte[] data = getBytes(columnIndex);

                        if (this.connection.getAutoDeserialize()) {
                              Object obj = data;

                              if ((data != null) && (data.length >= 2)) {
                                    if ((data[0] == -84) && (data[1] == -19)) {
                                          // Serialized object?
                                          try {
                                                ByteArrayInputStream bytesIn = new ByteArrayInputStream(
                                                            data);
                                                ObjectInputStream objIn = new ObjectInputStream(
                                                            bytesIn);
                                                obj = objIn.readObject();
                                                objIn.close();
                                                bytesIn.close();
                                          } catch (ClassNotFoundException cnfe) {
                                                throw SQLError.createSQLException(
                                                            Messages
                                                                        .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
                                                                        + cnfe.toString()
                                                                        + Messages
                                                                                    .getString("ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$
                                          } catch (IOException ex) {
                                                obj = data; // not serialized?
                                          }
                                    } else {
                                          return getString(columnIndex);
                                    }
                              }

                              return obj;
                        }

                        return data;
                  }
                  
                  return getBytes(columnIndex); 

            case Types.DATE:
                  if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
                              && !this.connection.getYearIsDateType()) {
                        return Constants.shortValueOf(getShort(columnIndex));
                  }

                  return getDate(columnIndex);

            case Types.TIME:
                  return getTime(columnIndex);

            case Types.TIMESTAMP:
                  return getTimestamp(columnIndex);

            default:
                  return getString(columnIndex);
            }
      }

      /**
       * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
       * determine the class from which to construct data of SQL structured and
       * distinct types.
       * 
       * @param i
       *            the first column is 1, the second is 2, ...
       * @param map
       *            the mapping from SQL type names to Java classes
       * 
       * @return an object representing the SQL value
       * 
       * @throws SQLException
       *             because this is not implemented
       */
04905       public Object getObject(int i, java.util.Map map) throws SQLException {
            return getObject(i);
      }

      /**
       * Get the value of a column in the current row as a Java object
       * 
       * <p>
       * This method will return the value of the given column as a Java object.
       * The type of the Java object will be the default Java Object type
       * corresponding to the column's SQL type, following the mapping specified
       * in the JDBC specification.
       * </p>
       * 
       * <p>
       * This method may also be used to read database specific abstract data
       * types.
       * </p>
       * 
       * @param columnName
       *            is the SQL name of the column
       * 
       * @return a Object holding the column value
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
04932       public Object getObject(String columnName) throws SQLException {
            return getObject(findColumn(columnName));
      }

      /**
       * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
       * determine the class from which to construct data of SQL structured and
       * distinct types.
       * 
       * @param colName
       *            the column name
       * @param map
       *            the mapping from SQL type names to Java classes
       * 
       * @return an object representing the SQL value
       * 
       * @throws SQLException
       *             as this is not implemented
       */
04951       public Object getObject(String colName, java.util.Map map)
                  throws SQLException {
            return getObject(findColumn(colName), map);
      }

04956       public Object getObjectStoredProc(int columnIndex, int desiredSqlType)
                  throws SQLException {
            checkRowPos();
            checkColumnBounds(columnIndex);

            Object value = this.thisRow.getColumnValue(columnIndex - 1);
            
            if (value == null) {
                  this.wasNullFlag = true;

                  return null;
            }
            
            this.wasNullFlag = false;

            Field field;
            field = this.fields[columnIndex - 1];

            switch (desiredSqlType) {
            case Types.BIT:
            case Types.BOOLEAN:
                  // valueOf would be nicer here, but it isn't
                  // present in JDK-1.3.1, which is what the CTS
                  // uses.
                  return Boolean.valueOf(getBoolean(columnIndex));

            case Types.TINYINT:
                  return Constants.integerValueOf(getInt(columnIndex));

            case Types.SMALLINT:
                  return Constants.integerValueOf(getInt(columnIndex));

            case Types.INTEGER:

                  if (!field.isUnsigned() || 
                              field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
                        return Constants.integerValueOf(getInt(columnIndex));
                  }

                  return Constants.longValueOf(getLong(columnIndex));

            case Types.BIGINT:

                  if (field.isUnsigned()) {
                        return getBigDecimal(columnIndex);
                  }

                  return Constants.longValueOf(getLong(columnIndex));

            case Types.DECIMAL:
            case Types.NUMERIC:

                  String stringVal = getString(columnIndex);
                  BigDecimal val;

                  if (stringVal != null) {
                        if (stringVal.length() == 0) {
                              val = new BigDecimal(0);

                              return val;
                        }

                        try {
                              val = new BigDecimal(stringVal);
                        } catch (NumberFormatException ex) {
                              throw SQLError.createSQLException(
                                          Messages
                                                      .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
                                                      + stringVal
                                                      + Messages
                                                                  .getString("ResultSet.___in_column__87")
                                                      + columnIndex + "(" //$NON-NLS-1$
                                                      + this.fields[columnIndex - 1] + ").",
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        }

                        return val;
                  }

                  return null;

            case Types.REAL:
                  return new Float(getFloat(columnIndex));

            case Types.FLOAT:

                  if (!this.connection.getRunningCTS13()) {
                        return new Double(getFloat(columnIndex));
                  } else {
                        return new Float(getFloat(columnIndex)); // NB - bug in JDBC
                                                                                          // compliance test,
                                                                                          // according
                        // to JDBC spec, FLOAT type should return DOUBLE
                        // but causes ClassCastException in CTS :(
                  }
            case Types.DOUBLE:
                  return new Double(getDouble(columnIndex));

            case Types.CHAR:
            case Types.VARCHAR:
                  return getString(columnIndex);
            case Types.LONGVARCHAR:
                  return getStringForClob(columnIndex);
            case Types.BINARY:
            case Types.VARBINARY:
            case Types.LONGVARBINARY:
                  return getBytes(columnIndex);

            case Types.DATE:
                  if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
                              && !this.connection.getYearIsDateType()) {
                        return Constants.shortValueOf(getShort(columnIndex));
                  }

                  return getDate(columnIndex);

            case Types.TIME:
                  return getTime(columnIndex);

            case Types.TIMESTAMP:
                  return getTimestamp(columnIndex);

            default:
                  return getString(columnIndex);
            }
      }

05083       public Object getObjectStoredProc(int i, java.util.Map map,
                  int desiredSqlType) throws SQLException {
            return getObjectStoredProc(i, desiredSqlType);
      }

05088       public Object getObjectStoredProc(String columnName, int desiredSqlType)
                  throws SQLException {
            return getObjectStoredProc(findColumn(columnName), desiredSqlType);
      }

05093       public Object getObjectStoredProc(String colName, java.util.Map map,
                  int desiredSqlType) throws SQLException {
            return getObjectStoredProc(findColumn(colName), map, desiredSqlType);
      }

      /**
       * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
       * 
       * @param i
       *            the first column is 1, the second is 2, ...
       * 
       * @return an object representing data of an SQL REF type
       * 
       * @throws SQLException
       *             as this is not implemented
       * @throws NotImplemented
       *             DOCUMENT ME!
       */
05111       public java.sql.Ref getRef(int i) throws SQLException {
            checkColumnBounds(i);
            throw new NotImplemented();
      }

      /**
       * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
       * 
       * @param colName
       *            the column name
       * 
       * @return an object representing data of an SQL REF type
       * 
       * @throws SQLException
       *             as this method is not implemented.
       * @throws NotImplemented
       *             DOCUMENT ME!
       */
05129       public java.sql.Ref getRef(String colName) throws SQLException {
            return getRef(findColumn(colName));
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Determine the current row number. The first row is number 1, the second
       * number 2, etc.
       * </p>
       * 
       * @return the current row number, else return 0 if there is no current row
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
05146       public int getRow() throws SQLException {
            checkClosed();

            int currentRowNumber = this.rowData.getCurrentRowNumber();
            int row = 0;

            // Non-dynamic result sets can be interrogated
            // for this information
            if (!this.rowData.isDynamic()) {
                  if ((currentRowNumber < 0) || this.rowData.isAfterLast()
                              || this.rowData.isEmpty()) {
                        row = 0;
                  } else {
                        row = currentRowNumber + 1;
                  }
            } else {
                  // dynamic (streaming) can not
                  row = currentRowNumber + 1;
            }

            return row;
      }

      /**
       * Returns the server info (if any), or null if none.
       * 
       * @return server info created for this ResultSet
       */
05174       public String getServerInfo() {
            return this.serverInfo;
      }

      private long getNumericRepresentationOfSQLBitType(int columnIndex) throws SQLException {
            
            Object value = this.thisRow.getColumnValue(columnIndex - 1);
            
            if (this.fields[columnIndex - 1].isSingleBit() || 
                        ((byte[])value).length == 1) {
                  return ((byte[])value)[0];
            }
            
            
            byte[] asBytes = (byte[])value;
            
            
            int shift = 0;
            
            long[] steps = new long[asBytes.length];
            
            for (int i = asBytes.length - 1; i >= 0; i--) {
                  steps[i] = (long)(asBytes[i] & 0xff) << shift;
                  shift += 8;
            }
            
            long valueAsLong = 0;
            
            for (int i = 0; i < asBytes.length; i++) {
                  valueAsLong |= steps[i];
            }
            
            return valueAsLong;
      }

      /**
       * Get the value of a column in the current row as a Java short.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2,...
       * 
       * @return the column value; 0 if SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
05220       public short getShort(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkRowPos();
                  
                  if (this.useFastIntParsing) {
                        
                        checkColumnBounds(columnIndex);

                        Object value = this.thisRow.getColumnValue(columnIndex - 1);
                        
                        if (value == null) {
                              this.wasNullFlag = true;
                        } else {
                              this.wasNullFlag = false;
                        }
                        
                        if (this.wasNullFlag) {
                              return 0;
                        }

                        byte[] shortAsBytes = (byte[]) value;

                        if (shortAsBytes.length == 0) {
                              return (short) convertToZeroWithEmptyCheck();
                        }

                        boolean needsFullParse = false;

                        for (int i = 0; i < shortAsBytes.length; i++) {
                              if (((char) shortAsBytes[i] == 'e')
                                          || ((char) shortAsBytes[i] == 'E')) {
                                    needsFullParse = true;

                                    break;
                              }
                        }

                        if (!needsFullParse) {
                              try {
                                    return parseShortWithOverflowCheck(columnIndex,
                                                shortAsBytes, null);
                              } catch (NumberFormatException nfe) {
                                    try {
                                          // To do: Warn of over/underflow???
                                          return parseShortAsDouble(columnIndex, new String(
                                                      shortAsBytes));
                                    } catch (NumberFormatException newNfe) {
                                          ; // ignore, it's not a number
                                    }

                                    if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                                          long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
                                          
                                          if (this.jdbcCompliantTruncationForReads &&
                                                      (valueAsLong < Short.MIN_VALUE
                                                                  || valueAsLong > Short.MAX_VALUE)) {
                                                throwRangeException(String.valueOf(valueAsLong), columnIndex,
                                                            Types.SMALLINT);
                                          }
                                          
                                          return (short)valueAsLong;
                                    }
                                    
                                    throw SQLError.createSQLException(
                                                Messages
                                                            .getString("ResultSet.Invalid_value_for_getShort()_-____96")
                                                            + new String(shortAsBytes) //$NON-NLS-1$
                                                            + "'",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                        }
                  }

                  String val = null;

                  try {
                        val = getString(columnIndex);

                        if ((val != null)) {

                              if (val.length() == 0) {
                                    return (short) convertToZeroWithEmptyCheck();
                              }

                              if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
                                          && (val.indexOf(".") == -1)) {
                                    return parseShortWithOverflowCheck(columnIndex, null,
                                                val);
                              }

                              // Convert floating point
                              return parseShortAsDouble(columnIndex, val);
                        }

                        return 0; // for NULL
                  } catch (NumberFormatException nfe) {
                        try {
                              return parseShortAsDouble(columnIndex, val);
                        } catch (NumberFormatException newNfe) {
                              ; // ignore, it's not a number
                        }

                        if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                              long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
                              
                              if (this.jdbcCompliantTruncationForReads &&
                                          (valueAsLong < Short.MIN_VALUE
                                                      || valueAsLong > Short.MAX_VALUE)) {
                                    throwRangeException(String.valueOf(valueAsLong), columnIndex,
                                                Types.SMALLINT);
                              }
                              
                              return (short)valueAsLong;
                        }
                        
                        throw SQLError.createSQLException(
                                    Messages
                                                .getString("ResultSet.Invalid_value_for_getShort()_-____96")
                                                + val //$NON-NLS-1$
                                                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                  }
            }

            return getNativeShort(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
05357       public short getShort(String columnName) throws SQLException {
            return getShort(findColumn(columnName));
      }

      private final short getShortFromString(String val, int columnIndex)
                  throws SQLException {
            try {
                  if ((val != null)) {

                        if (val.length() == 0) {
                              return (short) convertToZeroWithEmptyCheck();
                        }

                        if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
                                    && (val.indexOf(".") == -1)) {
                              return parseShortWithOverflowCheck(columnIndex, null, val);
                        }

                        // Convert floating point
                        return parseShortAsDouble(columnIndex, val);
                  }

                  return 0; // for NULL
            } catch (NumberFormatException nfe) {
                  try {
                        return parseShortAsDouble(columnIndex, val);
                  } catch (NumberFormatException newNfe) {
                        ; // ignore, it's not a number
                  }

                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Invalid_value_for_getShort()_-____217")
                                          + val //$NON-NLS-1$
                                          + Messages.getString("ResultSet.___in_column__218")
                                          + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * JDBC 2.0 Return the Statement that produced the ResultSet.
       * 
       * @return the Statment that produced the result set, or null if the result
       *         was produced some other way.
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
05405       public java.sql.Statement getStatement() throws SQLException {
            if (this.isClosed && !this.retainOwningStatement) {
                  throw SQLError.createSQLException(
                              "Operation not allowed on closed ResultSet. Statements "
                                          + "can be retained over result set closure by setting the connection property "
                                          + "\"retainStatementAfterResultSetClose\" to \"true\".",
                              SQLError.SQL_STATE_GENERAL_ERROR);

            }
            
            if (this.wrapperStatement != null) {
                  return this.wrapperStatement;
            }

            return this.owningStatement;
      }

      /**
       * Get the value of a column in the current row as a Java String
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value, null for SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
05433       public String getString(int columnIndex) throws SQLException {
            String stringVal = getStringInternal(columnIndex, true);
            
            if (this.padCharsWithSpace) {
                  Field f = this.fields[columnIndex - 1];
                  
                  if (f.getMysqlType() == MysqlDefs.FIELD_TYPE_STRING ) {
                        int fieldLength = (int)f.getLength() /* safe, bytes in a CHAR <= 1024 */ / 
                              f.getMaxBytesPerCharacter(); /* safe, this will never be 0 */
                        
                        int currentLength = stringVal.length();
                        
                        if (currentLength < fieldLength) {
                              StringBuffer paddedBuf = new StringBuffer(fieldLength);
                              paddedBuf.append(stringVal);
                              
                              int difference = fieldLength - currentLength;
                              
                              paddedBuf.append(EMPTY_SPACE, 0, difference);
                              
                              stringVal = paddedBuf.toString();
                        }
                  }
            }
            
            return stringVal;
      }

      /**
       * The following routines simply convert the columnName into a columnIndex
       * and then call the appropriate routine above.
       * 
       * @param columnName
       *            is the SQL name of the column
       * 
       * @return the column value
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
05473       public String getString(String columnName) throws SQLException {
            return getString(findColumn(columnName));
      }

      private String getStringForClob(int columnIndex) throws SQLException {
            String asString = null;
            
            String forcedEncoding = 
                  this.connection.getClobCharacterEncoding();
            
            if (forcedEncoding == null) {
                  if (!this.isBinaryEncoded) {
                        asString = getString(columnIndex);
                  } else {
                        asString = getNativeString(columnIndex);
                  }
            } else {
                  try {
                        byte[] asBytes = null;
                        
                        if (!this.isBinaryEncoded) {
                              asBytes = getBytes(columnIndex);
                        } else {
                              asBytes = getNativeBytes(columnIndex, true);
                        }
                        
                        if (asBytes != null) {
                              asString = new String(asBytes, forcedEncoding);
                        }
                  } catch (UnsupportedEncodingException uee) {
                        throw SQLError.createSQLException("Unsupported character encoding " + 
                                    forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                  }
            }
            
            return asString;
      }

      protected String getStringInternal(int columnIndex, boolean checkDateTypes)
                  throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkRowPos();
                  checkColumnBounds(columnIndex);

                  if (this.fields == null) {
                        throw SQLError.createSQLException(
                                    Messages
                                                .getString("ResultSet.Query_generated_no_fields_for_ResultSet_99"), //$NON-NLS-1$
                                    SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
                  }

                  // JDBC is 1-based, Java is not !?
                  
                  int internalColumnIndex = columnIndex - 1;
                  
                  if (this.thisRow.isNull(internalColumnIndex)) {
                        this.wasNullFlag = true;

                        return null;
                  }

                  this.wasNullFlag = false;

                  
                  Field metadata = this.fields[internalColumnIndex];
                  
                  String stringVal = null;
                  
                  if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
                        if (metadata.isSingleBit()) {
                              byte[] value = this.thisRow.getColumnValue(internalColumnIndex);
                              
                              if (value.length == 0) {
                                    return String.valueOf(convertToZeroWithEmptyCheck());
                              }
                              
                              return String.valueOf(value[0]);
                        }
                        
                        return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
                  }
                  
                  String encoding = metadata.getCharacterSet();

                  stringVal = this.thisRow.getString(internalColumnIndex, encoding, this.connection);

                  //
                  // Special handling for YEAR type from mysql, some people
                  // want it as a DATE, others want to treat it as a SHORT
                  //

                  if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
                        if (!this.connection.getYearIsDateType()) {
                              return stringVal;
                        }

                        Date dt = getDateFromString(stringVal, columnIndex);

                        if (dt == null) {
                              this.wasNullFlag = true;

                              return null;
                        }

                        this.wasNullFlag = false;

                        return dt.toString();
                  }

                  // Handles timezone conversion and zero-date behavior

                  if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) {
                        switch (metadata.getSQLType()) {
                        case Types.TIME:
                              Time tm = getTimeFromString(stringVal, null, columnIndex,
                                          this.getDefaultTimeZone(), false);

                              if (tm == null) {
                                    this.wasNullFlag = true;

                                    return null;
                              }

                              this.wasNullFlag = false;

                              return tm.toString();
                        case Types.DATE:

                              Date dt = getDateFromString(stringVal, columnIndex);

                              if (dt == null) {
                                    this.wasNullFlag = true;

                                    return null;
                              }

                              this.wasNullFlag = false;

                              return dt.toString();
                        case Types.TIMESTAMP:
                              Timestamp ts = getTimestampFromString(columnIndex,
                                          null, stringVal, this.getDefaultTimeZone(), false);

                              if (ts == null) {
                                    this.wasNullFlag = true;

                                    return null;
                              }

                              this.wasNullFlag = false;

                              return ts.toString();
                        default:
                              break;
                        }
                  }

                  return stringVal;
            }

            return getNativeString(columnIndex);
      }

      /**
       * Get the value of a column in the current row as a java.sql.Time object
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value; null if SQL NULL
       * 
       * @throws java.sql.SQLException
       *             if a database access error occurs
       */
05647       public Time getTime(int columnIndex) throws java.sql.SQLException {
            return getTimeInternal(columnIndex, null, this.getDefaultTimeZone(), false);
      }

      /**
       * Get the value of a column in the current row as a java.sql.Time object.
       * Use the calendar to construct an appropriate millisecond value for the
       * Time, if the underlying database doesn't store timezone information.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param cal
       *            the calendar to use in constructing the time
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
05666       public java.sql.Time getTime(int columnIndex, Calendar cal)
                  throws SQLException {
            return getTimeInternal(columnIndex, cal, cal.getTimeZone(), true);
      }

      /**
       * Get the value of a column in the current row as a java.sql.Time object.
       * 
       * @param columnName
       *            is the SQL name of the column
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @throws java.sql.SQLException
       *             if a database-access error occurs.
       */
05682       public Time getTime(String columnName) throws java.sql.SQLException {
            return getTime(findColumn(columnName));
      }

      /**
       * Get the value of a column in the current row as a java.sql.Time object.
       * Use the calendar to construct an appropriate millisecond value for the
       * Time, if the underlying database doesn't store timezone information.
       * 
       * @param columnName
       *            is the SQL name of the column
       * @param cal
       *            the calendar to use in constructing the time
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
05701       public java.sql.Time getTime(String columnName, Calendar cal)
                  throws SQLException {
            return getTime(findColumn(columnName), cal);
      }

      private Time getTimeFromString(String timeAsString, Calendar targetCalendar,
                  int columnIndex,
                  TimeZone tz, 
                  boolean rollForward) throws SQLException {
            int hr = 0;
            int min = 0;
            int sec = 0;

            try {
                  
                  if (timeAsString == null) {
                        this.wasNullFlag = true;

                        return null;
                  } 
                  
                  //
                  // JDK-6 doesn't like trailing whitespace
                  //
                  // Note this isn't a performance issue, other
                  // than the iteration over the string, as String.trim()
                  // will return a new string only if whitespace is present
                  //
                  
                  timeAsString = timeAsString.trim();
                  
                  if (timeAsString.equals("0")
                              || timeAsString.equals("0000-00-00")
                              || timeAsString.equals("0000-00-00 00:00:00")
                              || timeAsString.equals("00000000000000")) {
                        if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                    .equals(this.connection.getZeroDateTimeBehavior())) {
                              this.wasNullFlag = true;

                              return null;
                        } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                    .equals(this.connection.getZeroDateTimeBehavior())) {
                              throw SQLError.createSQLException("Value '" + timeAsString
                                          + "' can not be represented as java.sql.Time",
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        }

                        // We're left with the case of 'round' to a time Java _can_
                        // represent, which is '00:00:00'
                        return fastTimeCreate(null, 0, 0, 0);
                  }

                  this.wasNullFlag = false;

                  Field timeColField = this.fields[columnIndex - 1];

                  if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
                        // It's a timestamp
                        int length = timeAsString.length();

                        switch (length) {
                        case 19: { // YYYY-MM-DD hh:mm:ss
                         
                                    hr = Integer.parseInt(timeAsString.substring(length - 8,
                                                length - 6));
                                    min = Integer.parseInt(timeAsString.substring(length - 5,
                                                length - 3));
                                    sec = Integer.parseInt(timeAsString.substring(length - 2,
                                                length));
                        }

                                    break;
                        case 14:
                        case 12: {
                              hr = Integer.parseInt(timeAsString.substring(length - 6,
                                          length - 4));
                              min = Integer.parseInt(timeAsString.substring(length - 4,
                                          length - 2));
                              sec = Integer.parseInt(timeAsString.substring(length - 2,
                                          length));
                        }

                              break;

                        case 10: {
                              hr = Integer.parseInt(timeAsString.substring(6, 8));
                              min = Integer.parseInt(timeAsString.substring(8, 10));
                              sec = 0;
                        }

                              break;

                        default:
                              throw SQLError.createSQLException(
                                          Messages
                                                      .getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$
                                                      + columnIndex
                                                      + "("
                                                      + this.fields[columnIndex - 1] + ").",
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        } /* endswitch */

                        SQLWarning precisionLost = new SQLWarning(
                                    Messages
                                                .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
                                                + columnIndex
                                                + "("
                                                + this.fields[columnIndex - 1] + ").");

                        if (this.warningChain == null) {
                              this.warningChain = precisionLost;
                        } else {
                              this.warningChain.setNextWarning(precisionLost);
                        }
                  } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
                        hr = Integer.parseInt(timeAsString.substring(11, 13));
                        min = Integer.parseInt(timeAsString.substring(14, 16));
                        sec = Integer.parseInt(timeAsString.substring(17, 19));

                        SQLWarning precisionLost = new SQLWarning(
                                    Messages
                                                .getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$
                                                + columnIndex
                                                + "("
                                                + this.fields[columnIndex - 1] + ").");

                        if (this.warningChain == null) {
                              this.warningChain = precisionLost;
                        } else {
                              this.warningChain.setNextWarning(precisionLost);
                        }
                  } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
                        return fastTimeCreate(null, 0, 0, 0); // midnight on the given
                                                                                    // date
                  } else {
                        // convert a String to a Time
                        if ((timeAsString.length() != 5)
                                    && (timeAsString.length() != 8)) {
                              throw SQLError.createSQLException(Messages
                                          .getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$
                                          + timeAsString
                                          + Messages.getString("ResultSet.___in_column__268")
                                          + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                        }

                        hr = Integer.parseInt(timeAsString.substring(0, 2));
                        min = Integer.parseInt(timeAsString.substring(3, 5));
                        sec = (timeAsString.length() == 5) ? 0 : Integer
                                    .parseInt(timeAsString.substring(6));
                  }

                  Calendar sessionCalendar = this.getCalendarInstanceForSessionOrNew();
                  
                  synchronized (sessionCalendar) {
                        return TimeUtil.changeTimezone(this.connection, 
                                    sessionCalendar,
                                    targetCalendar, 
                                    fastTimeCreate(
                                    sessionCalendar, hr, min, sec), 
                                    this.connection.getServerTimezoneTZ(),
                                    tz, rollForward);
                  }
            } catch (Exception ex) {
                  throw SQLError.createSQLException(ex.toString(),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
            }
      }
      
      /**
       * Get the value of a column in the current row as a java.sql.Time object in
       * the given timezone
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * @param tz
       *            the Timezone to use
       * 
       * @return the column value; null if SQL NULL
       * 
       * @exception java.sql.SQLException
       *                if a database access error occurs
       */
05883       private Time getTimeInternal(int columnIndex, Calendar targetCalendar,
                  TimeZone tz,
                  boolean rollForward) throws java.sql.SQLException {
            if (this.isBinaryEncoded) {
                  return getNativeTime(columnIndex, targetCalendar, tz, rollForward);
            }

            if (!this.useFastDateParsing) {
                  String timeAsString = getStringInternal(columnIndex, false);

                  return getTimeFromString(timeAsString, targetCalendar,
                        columnIndex, tz, rollForward);
            }
            
            checkColumnBounds(columnIndex);
            
            int columnIndexMinusOne = columnIndex - 1;
            
            if (this.thisRow.isNull(columnIndexMinusOne)) {
                  this.wasNullFlag = true;
                  
                  return null;
            }
            
            this.wasNullFlag = false;
            
            return this.thisRow.getTimeFast(columnIndexMinusOne, 
                        targetCalendar, tz, rollForward, this.connection, this);
      }

      /**
       * Get the value of a column in the current row as a java.sql.Timestamp
       * object
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return the column value; null if SQL NULL
       * 
       * @exception java.sql.SQLException
       *                if a database access error occurs
       */
05925       public Timestamp getTimestamp(int columnIndex) throws java.sql.SQLException {
            checkColumnBounds(columnIndex);
            
            return getTimestampInternal(columnIndex, null, this.getDefaultTimeZone(),
                        false);
      }

      /**
       * Get the value of a column in the current row as a java.sql.Timestamp
       * object. Use the calendar to construct an appropriate millisecond value
       * for the Timestamp, if the underlying database doesn't store timezone
       * information.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param cal
       *            the calendar to use in constructing the timestamp
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
05948       public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
                  throws SQLException {
            return getTimestampInternal(columnIndex, cal, cal.getTimeZone(), true);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws java.sql.SQLException
       *             DOCUMENT ME!
       */
05964       public Timestamp getTimestamp(String columnName)
                  throws java.sql.SQLException {
            return getTimestamp(findColumn(columnName));
      }

      /**
       * Get the value of a column in the current row as a java.sql.Timestamp
       * object. Use the calendar to construct an appropriate millisecond value
       * for the Timestamp, if the underlying database doesn't store timezone
       * information.
       * 
       * @param columnName
       *            is the SQL name of the column
       * @param cal
       *            the calendar to use in constructing the timestamp
       * 
       * @return the column value; if the value is SQL NULL, the result is null
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
05985       public java.sql.Timestamp getTimestamp(String columnName, Calendar cal)
                  throws SQLException {
            return getTimestamp(findColumn(columnName), cal);
      }

      private Timestamp getTimestampFromString(int columnIndex,
                  Calendar targetCalendar,
                  String timestampValue, TimeZone tz, boolean rollForward)
      throws java.sql.SQLException {
            try {
                  this.wasNullFlag = false;
                  
                  if (timestampValue == null) {
                        this.wasNullFlag = true;
                        
                        return null;
                  }
                  
                  //
                  // JDK-6 doesn't like trailing whitespace
                  //
                  // Note this isn't a performance issue, other
                  // than the iteration over the string, as String.trim()
                  // will return a new string only if whitespace is present
                  //
                  
                  timestampValue = timestampValue.trim();
                  
                  int length = timestampValue.length();
                  
                  Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
                              this.connection.getUtcCalendar() : 
                                    getCalendarInstanceForSessionOrNew();
                  
                  synchronized (sessionCalendar) {
                        if ((length > 0)
                                    && (timestampValue.charAt(0) == '0')
                                    && (timestampValue.equals("0000-00-00")
                                                || timestampValue.equals("0000-00-00 00:00:00")
                                                || timestampValue.equals("00000000000000") || timestampValue
                                                .equals("0"))) {
                              
                              if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                          .equals(this.connection.getZeroDateTimeBehavior())) {
                                    this.wasNullFlag = true;
                                    
                                    return null;
                              } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                          .equals(this.connection.getZeroDateTimeBehavior())) {
                                    throw SQLError.createSQLException("Value '" + timestampValue
                                                + "' can not be represented as java.sql.Timestamp",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                              
                              // We're left with the case of 'round' to a date Java _can_
                              // represent, which is '0001-01-01'.
                              return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
                              
                        } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
                              
                              return TimeUtil.changeTimezone(this.connection,
                                          sessionCalendar, 
                                          targetCalendar,
                                          fastTimestampCreate(sessionCalendar, 
                                                      Integer
                                                      .parseInt(timestampValue.substring(0, 4)), 1,
                                                      1, 0, 0, 0, 0), this.connection
                                                      .getServerTimezoneTZ(), tz, rollForward);
                              
                        } else {
                              if (timestampValue.endsWith(".")) {
                                    timestampValue = timestampValue.substring(0, timestampValue
                                                .length() - 1);
                              }
                              
                              // Convert from TIMESTAMP or DATE
                              switch (length) {
                              case 26:
                              case 25:
                              case 24:
                              case 23:
                              case 22:
                              case 21:
                              case 20:
                              case 19: {
                                    int year = Integer.parseInt(timestampValue.substring(0, 4));
                                    int month = Integer
                                    .parseInt(timestampValue.substring(5, 7));
                                    int day = Integer.parseInt(timestampValue.substring(8, 10));
                                    int hour = Integer.parseInt(timestampValue
                                                .substring(11, 13));
                                    int minutes = Integer.parseInt(timestampValue.substring(14,
                                                16));
                                    int seconds = Integer.parseInt(timestampValue.substring(17,
                                                19));
                                    
                                    int nanos = 0;
                                    
                                    if (length > 19) {
                                          int decimalIndex = timestampValue.lastIndexOf('.');
                                          
                                          if (decimalIndex != -1) {
                                                if ((decimalIndex + 2) <= timestampValue.length()) {
                                                      nanos = Integer.parseInt(timestampValue
                                                                  .substring(decimalIndex + 1));
                                                } else {
                                                      throw new IllegalArgumentException(); // re-thrown
                                                      // further
                                                      // down
                                                      // with
                                                      // a
                                                      // much better error message
                                                }
                                          }
                                    }
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
                                                            minutes, seconds, nanos), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 14: {
                                    int year = Integer.parseInt(timestampValue.substring(0, 4));
                                    int month = Integer
                                    .parseInt(timestampValue.substring(4, 6));
                                    int day = Integer.parseInt(timestampValue.substring(6, 8));
                                    int hour = Integer
                                    .parseInt(timestampValue.substring(8, 10));
                                    int minutes = Integer.parseInt(timestampValue.substring(10,
                                                12));
                                    int seconds = Integer.parseInt(timestampValue.substring(12,
                                                14));
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar, 
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
                                                            minutes, seconds, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 12: {
                                    int year = Integer.parseInt(timestampValue.substring(0, 2));
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    int month = Integer
                                    .parseInt(timestampValue.substring(2, 4));
                                    int day = Integer.parseInt(timestampValue.substring(4, 6));
                                    int hour = Integer.parseInt(timestampValue.substring(6, 8));
                                    int minutes = Integer.parseInt(timestampValue.substring(8,
                                                10));
                                    int seconds = Integer.parseInt(timestampValue.substring(10,
                                                12));
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year + 1900, month, day,
                                                            hour, minutes, seconds, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 10: {
                                    int year;
                                    int month;
                                    int day;
                                    int hour;
                                    int minutes;
                                    
                                    if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
                                                || (timestampValue.indexOf("-") != -1)) {
                                          year = Integer.parseInt(timestampValue.substring(0, 4));
                                          month = Integer
                                          .parseInt(timestampValue.substring(5, 7));
                                          day = Integer.parseInt(timestampValue.substring(8, 10));
                                          hour = 0;
                                          minutes = 0;
                                    } else {
                                          year = Integer.parseInt(timestampValue.substring(0, 2));
                                          
                                          if (year <= 69) {
                                                year = (year + 100);
                                          }
                                          
                                          month = Integer
                                          .parseInt(timestampValue.substring(2, 4));
                                          day = Integer.parseInt(timestampValue.substring(4, 6));
                                          hour = Integer.parseInt(timestampValue.substring(6, 8));
                                          minutes = Integer.parseInt(timestampValue.substring(8,
                                                      10));
                                          
                                          year += 1900; // two-digit year
                                    }
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
                                                            minutes, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 8: {
                                    if (timestampValue.indexOf(":") != -1) {
                                          int hour = Integer.parseInt(timestampValue.substring(0,
                                                      2));
                                          int minutes = Integer.parseInt(timestampValue
                                                      .substring(3, 5));
                                          int seconds = Integer.parseInt(timestampValue
                                                      .substring(6, 8));
                                          
                                          return TimeUtil
                                          .changeTimezone(this.connection,
                                                      sessionCalendar,
                                                      targetCalendar,
                                                      fastTimestampCreate(sessionCalendar, 1970, 1, 1,
                                                                  hour, minutes, seconds, 0),
                                                                  this.connection.getServerTimezoneTZ(),
                                                                  tz, rollForward);
                                          
                                    }
                                    
                                    int year = Integer.parseInt(timestampValue.substring(0, 4));
                                    int month = Integer
                                    .parseInt(timestampValue.substring(4, 6));
                                    int day = Integer.parseInt(timestampValue.substring(6, 8));
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year - 1900, month - 1,
                                                            day, 0, 0, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 6: {
                                    int year = Integer.parseInt(timestampValue.substring(0, 2));
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    int month = Integer
                                    .parseInt(timestampValue.substring(2, 4));
                                    int day = Integer.parseInt(timestampValue.substring(4, 6));
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year + 1900, month, day,
                                                            0, 0, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 4: {
                                    int year = Integer.parseInt(timestampValue.substring(0, 2));
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    int month = Integer
                                    .parseInt(timestampValue.substring(2, 4));
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year + 1900, month, 1, 0,
                                                            0, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 2: {
                                    int year = Integer.parseInt(timestampValue.substring(0, 2));
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(null, year + 1900, 1, 1, 0, 0,
                                                            0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              default:
                                    throw new java.sql.SQLException(
                                                "Bad format for Timestamp '" + timestampValue
                                                + "' in column " + columnIndex + ".",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                        }
                  }
            } catch (Exception e) {
                  throw new java.sql.SQLException("Cannot convert value '"
                              + timestampValue + "' from column " + columnIndex
                              + " to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
            }
            
      }

      private Timestamp getTimestampFromBytes(int columnIndex,
                  Calendar targetCalendar,
                  byte[] timestampAsBytes, TimeZone tz, boolean rollForward)
      throws java.sql.SQLException {
            checkColumnBounds(columnIndex);
            
            try {
                  this.wasNullFlag = false;
                  
                  if (timestampAsBytes == null) {
                        this.wasNullFlag = true;
                        
                        return null;
                  }

                  int length = timestampAsBytes.length;
                  
                  Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
                              this.connection.getUtcCalendar() : 
                                    getCalendarInstanceForSessionOrNew();
                  
                  synchronized (sessionCalendar) {
                        boolean allZeroTimestamp = true;
                        
                        boolean onlyTimePresent = StringUtils.indexOf(timestampAsBytes, ':') != -1;
                        
                        for (int i = 0; i < length; i++) {
                              byte b = timestampAsBytes[i];

                              if (b == ' ' || b == '-' || b == '/') {
                                    onlyTimePresent = false;
                              }

                              if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/'
                                          && b != '.') {
                                    allZeroTimestamp = false;

                                    break;
                              }
                        }

                        if (!onlyTimePresent && allZeroTimestamp) {
                              
                              if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                          .equals(this.connection.getZeroDateTimeBehavior())) {
                                    this.wasNullFlag = true;
                                    
                                    return null;
                              } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                          .equals(this.connection.getZeroDateTimeBehavior())) {
                                    throw SQLError.createSQLException("Value '" + timestampAsBytes
                                                + "' can not be represented as java.sql.Timestamp",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                              
                              // We're left with the case of 'round' to a date Java _can_
                              // represent, which is '0001-01-01'.
                              return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
                              
                        } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
                              
                              return TimeUtil.changeTimezone(this.connection,
                                          sessionCalendar, 
                                          targetCalendar,
                                          fastTimestampCreate(sessionCalendar, 
                                                      StringUtils.getInt(timestampAsBytes, 0, 4), 1,
                                                      1, 0, 0, 0, 0), this.connection
                                                      .getServerTimezoneTZ(), tz, rollForward);
                              
                        } else {
                              if (timestampAsBytes[length - 1] == '.') {
                                    length--;
                              }
                              
                              // Convert from TIMESTAMP or DATE
                              switch (length) {
                              case 26:
                              case 25:
                              case 24:
                              case 23:
                              case 22:
                              case 21:
                              case 20:
                              case 19: {
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 4);
                                    int month = StringUtils.getInt(timestampAsBytes, 5, 7);
                                    int day = StringUtils.getInt(timestampAsBytes, 8, 10);
                                    int hour = StringUtils.getInt(timestampAsBytes, 11, 13);
                                    int minutes = StringUtils.getInt(timestampAsBytes, 14, 16);
                                    int seconds = StringUtils.getInt(timestampAsBytes, 17, 19);
                                    
                                    int nanos = 0;
                                    
                                    if (length > 19) {
                                          int decimalIndex = StringUtils.lastIndexOf(timestampAsBytes, '.');
                                          
                                          if (decimalIndex != -1) {
                                                if ((decimalIndex + 2) <= length) {
                                                      nanos = StringUtils.getInt(timestampAsBytes, decimalIndex + 1, length);
                                                } else {
                                                      throw new IllegalArgumentException(); // re-thrown
                                                      // further
                                                      // down
                                                      // with
                                                      // a
                                                      // much better error message
                                                }
                                          }
                                    }
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
                                                            minutes, seconds, nanos), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 14: {
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 4);
                                    int month = StringUtils.getInt(timestampAsBytes, 4, 6);
                                    int day = StringUtils.getInt(timestampAsBytes, 6, 8);
                                    int hour = StringUtils.getInt(timestampAsBytes, 8, 10);
                                    int minutes = StringUtils.getInt(timestampAsBytes, 10, 12);
                                    int seconds = StringUtils.getInt(timestampAsBytes, 12, 14);
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar, 
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
                                                            minutes, seconds, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 12: {
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 2);
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    int month = StringUtils.getInt(timestampAsBytes, 2, 4);
                                    int day = StringUtils.getInt(timestampAsBytes, 4, 6);
                                    int hour = StringUtils.getInt(timestampAsBytes, 6, 8);
                                    int minutes = StringUtils.getInt(timestampAsBytes, 8, 10);
                                    int seconds = StringUtils.getInt(timestampAsBytes, 10, 12);
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year + 1900, month, day,
                                                            hour, minutes, seconds, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 10: {
                                    int year;
                                    int month;
                                    int day;
                                    int hour;
                                    int minutes;
                                    
                                    if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
                                                || (StringUtils.indexOf(timestampAsBytes, '-') != -1)) {
                                          year = StringUtils.getInt(timestampAsBytes, 0, 4);
                                          month = StringUtils.getInt(timestampAsBytes, 5, 7);
                                          day = StringUtils.getInt(timestampAsBytes, 8, 10);
                                          hour = 0;
                                          minutes = 0;
                                    } else {
                                          year = StringUtils.getInt(timestampAsBytes, 0, 2);
                                          
                                          if (year <= 69) {
                                                year = (year + 100);
                                          }
                                          
                                          month = StringUtils.getInt(timestampAsBytes, 2, 4);
                                          day = StringUtils.getInt(timestampAsBytes, 4, 6);
                                          hour = StringUtils.getInt(timestampAsBytes, 6, 8);
                                          minutes = StringUtils.getInt(timestampAsBytes, 8, 10);
                                          
                                          year += 1900; // two-digit year
                                    }
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
                                                            minutes, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 8: {
                                    if (StringUtils.indexOf(timestampAsBytes, ':') != -1) {
                                          int hour = StringUtils.getInt(timestampAsBytes, 0, 2);
                                          int minutes = StringUtils.getInt(timestampAsBytes, 3, 5);
                                          int seconds = StringUtils.getInt(timestampAsBytes, 6, 8);
                                          
                                          return TimeUtil
                                          .changeTimezone(this.connection,
                                                      sessionCalendar,
                                                      targetCalendar,
                                                      fastTimestampCreate(sessionCalendar, 1970, 1, 1,
                                                                  hour, minutes, seconds, 0),
                                                                  this.connection.getServerTimezoneTZ(),
                                                                  tz, rollForward);
                                          
                                    }
                                    
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 4);
                                    int month = StringUtils.getInt(timestampAsBytes, 4, 6);
                                    int day = StringUtils.getInt(timestampAsBytes, 6, 8);
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year - 1900, month - 1,
                                                            day, 0, 0, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 6: {
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 2);
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    int month = StringUtils.getInt(timestampAsBytes, 2, 4);
                                    int day = StringUtils.getInt(timestampAsBytes, 4, 6);
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year + 1900, month, day,
                                                            0, 0, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 4: {
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 2);
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    int month = StringUtils.getInt(timestampAsBytes, 2, 4);
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(sessionCalendar, year + 1900, month, 1, 0,
                                                            0, 0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              case 2: {
                                    int year = StringUtils.getInt(timestampAsBytes, 0, 2);
                                    
                                    if (year <= 69) {
                                          year = (year + 100);
                                    }
                                    
                                    return TimeUtil.changeTimezone(this.connection,
                                                sessionCalendar,
                                                targetCalendar,
                                                fastTimestampCreate(null, year + 1900, 1, 1, 0, 0,
                                                            0, 0), this.connection
                                                            .getServerTimezoneTZ(), tz, rollForward);
                              }
                              
                              default:
                                    throw new java.sql.SQLException(
                                                "Bad format for Timestamp '" + new String(timestampAsBytes)
                                                + "' in column " + columnIndex + ".",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                        }
                  }
            } catch (Exception e) {
                  throw new java.sql.SQLException("Cannot convert value '"
                              + new String(timestampAsBytes) + "' from column " + columnIndex
                              + " to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
            }     
      }
      
      /**
       * Get the value of a column in the current row as a java.sql.Timestamp
       * object in the given timezone
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * @param tz
       *            the timezone to use
       * 
       * @return the column value; null if SQL NULL
       * 
       * @exception java.sql.SQLException
       *                if a database access error occurs
       */
06594       private Timestamp getTimestampInternal(int columnIndex, Calendar targetCalendar,
                  TimeZone tz,
                  boolean rollForward) throws java.sql.SQLException {
            if (this.isBinaryEncoded) {
                  return getNativeTimestamp(columnIndex, targetCalendar, tz, rollForward);
            }

            Timestamp tsVal = null;
            
            if (!this.useFastDateParsing) {
                  String timestampValue = getStringInternal(columnIndex, false);

                  tsVal = getTimestampFromString(columnIndex, targetCalendar, 
                              timestampValue, tz,
                              rollForward);
            } else {
                  tsVal = this.thisRow.getTimestampFast(columnIndex - 1, 
                              targetCalendar, tz, rollForward, this.connection, this);
            }
            
            if (tsVal == null) {
                  this.wasNullFlag = true;
            } else {
                  this.wasNullFlag = false;
            }
            
            return tsVal;
      }

      /**
       * JDBC 2.0 Return the type of this result set. The type is determined based
       * on the statement that created the result set.
       * 
       * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
       *         TYPE_SCROLL_SENSITIVE
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
06633       public int getType() throws SQLException {
            return this.resultSetType;
      }

      /**
       * A column value can also be retrieved as a stream of Unicode characters.
       * We implement this as a binary stream.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2...
       * 
       * @return a Java InputStream that delivers the database column value as a
       *         stream of two byte Unicode characters. If the value is SQL NULL,
       *         then the result is null
       * 
       * @exception SQLException
       *                if a database access error occurs
       * 
       * @see getAsciiStream
       * @see getBinaryStream
       * @deprecated
       */
06655       public InputStream getUnicodeStream(int columnIndex) throws SQLException {
            if (!this.isBinaryEncoded) {
                  checkRowPos();

                  return getBinaryStream(columnIndex);
            }

            return getNativeBinaryStream(columnIndex);
      }

      /**
       * DOCUMENT ME!
       * 
       * @param columnName
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       * 
       * @deprecated
       */
06678       public InputStream getUnicodeStream(String columnName) throws SQLException {
            return getUnicodeStream(findColumn(columnName));
      }

06682       public long getUpdateCount() {
            return this.updateCount;
      }

06686       public long getUpdateID() {
            return this.updateId;
      }

      /**
       * @see ResultSetInternalMethods#getURL(int)
       */
06693       public URL getURL(int colIndex) throws SQLException {
            String val = getString(colIndex);

            if (val == null) {
                  return null;
            }

            try {
                  return new URL(val);
            } catch (MalformedURLException mfe) {
                  throw SQLError.createSQLException(Messages
                              .getString("ResultSet.Malformed_URL____104")
                              + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * @see ResultSetInternalMethods#getURL(String)
       */
06712       public URL getURL(String colName) throws SQLException {
            String val = getString(colName);

            if (val == null) {
                  return null;
            }

            try {
                  return new URL(val);
            } catch (MalformedURLException mfe) {
                  throw SQLError.createSQLException(Messages
                              .getString("ResultSet.Malformed_URL____107")
                              + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      /**
       * The first warning reported by calls on this ResultSet is returned.
       * Subsequent ResultSet warnings will be chained to this
       * java.sql.SQLWarning.
       * 
       * <p>
       * The warning chain is automatically cleared each time a new row is read.
       * </p>
       * 
       * <p>
       * <B>Note:</B> This warning chain only covers warnings caused by ResultSet
       * methods. Any warnings caused by statement methods (such as reading OUT
       * parameters) will be chained on the Statement object.
       * </p>
       * 
       * @return the first java.sql.SQLWarning or null;
       * 
       * @exception SQLException
       *                if a database access error occurs.
       */
06748       public java.sql.SQLWarning getWarnings() throws SQLException {
            return this.warningChain;
      }

      /**
       * JDBC 2.0 Insert the contents of the insert row into the result set and
       * the database. Must be on the insert row when this method is called.
       * 
       * @exception SQLException
       *                if a database-access error occurs, if called when not on
       *                the insert row, or if all non-nullable columns in the
       *                insert row have not been given a value
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
06763       public void insertRow() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Determine if the cursor is after the last row in the result set.
       * </p>
       * 
       * @return true if after the last row, false otherwise. Returns false when
       *         the result set contains no rows.
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
06780       public boolean isAfterLast() throws SQLException {
            checkClosed();

            boolean b = this.rowData.isAfterLast();

            return b;
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Determine if the cursor is before the first row in the result set.
       * </p>
       * 
       * @return true if before the first row, false otherwise. Returns false when
       *         the result set contains no rows.
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
06801       public boolean isBeforeFirst() throws SQLException {
            checkClosed();

            return this.rowData.isBeforeFirst();
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Determine if the cursor is on the first row of the result set.
       * </p>
       * 
       * @return true if on the first row, false otherwise.
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
06819       public boolean isFirst() throws SQLException {
            checkClosed();

            return this.rowData.isFirst();
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Determine if the cursor is on the last row of the result set. Note:
       * Calling isLast() may be expensive since the JDBC driver might need to
       * fetch ahead one row in order to determine whether the current row is the
       * last row in the result set.
       * </p>
       * 
       * @return true if on the last row, false otherwise.
       * 
       * @exception SQLException
       *                if a database-access error occurs.
       */
06840       public boolean isLast() throws SQLException {
            checkClosed();

            return this.rowData.isLast();
      }

      /**
       * @param string
       * @param mysqlType
       * @param s
       */
06851       private void issueConversionViaParsingWarning(String methodName,
                  int columnIndex, Object value, Field fieldInfo,
                  int[] typesWithNoParseConversion) throws SQLException {
            
            StringBuffer originalQueryBuf = new StringBuffer();
            
            if (this.owningStatement != null
                        && this.owningStatement instanceof com.mysql.jdbc.PreparedStatement) {
                  originalQueryBuf.append(Messages.getString("ResultSet.CostlyConversionCreatedFromQuery"));
                  originalQueryBuf
                              .append(((com.mysql.jdbc.PreparedStatement) this.owningStatement).originalSql);
                  originalQueryBuf.append("\n\n");
            } else {
                  originalQueryBuf.append(".");
            }
            
            StringBuffer convertibleTypesBuf = new StringBuffer();
            
            for (int i = 0; i < typesWithNoParseConversion.length; i++) {
                  convertibleTypesBuf.append(MysqlDefs.typeToName(typesWithNoParseConversion[i]));
                  convertibleTypesBuf.append("\n");
            }
            
            String message = Messages.getString("ResultSet.CostlyConversion", new Object[] {
                        methodName,
                        new Integer(columnIndex + 1),
                        fieldInfo.getOriginalName(),
                        fieldInfo.getOriginalTableName(),
                        originalQueryBuf.toString(),
                        value != null ? value.getClass().getName() : ResultSetMetaData.getClassNameForJavaType(
                                    fieldInfo.getSQLType(), 
                                    fieldInfo.isUnsigned(), 
                                    fieldInfo.getMysqlType(), 
                                    fieldInfo.isBinary() || fieldInfo.isBlob(),
                                    fieldInfo.isOpaqueBinary()),
                        MysqlDefs.typeToName(fieldInfo.getMysqlType()),
                        convertibleTypesBuf.toString()});
                        
            this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN,
                        "", (this.owningStatement == null) ? "N/A"
                                    : this.owningStatement.currentCatalog,
                        this.connectionId, (this.owningStatement == null) ? (-1)
                                    : this.owningStatement.getId(), this.resultId, System
                                    .currentTimeMillis(), 0, Constants.MILLIS_I18N, null,
                        this.pointOfOrigin, message));

      }
      
      /**
       * JDBC 2.0
       * 
       * <p>
       * Moves to the last row in the result set.
       * </p>
       * 
       * @return true if on a valid row, false if no rows in the result set.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or result set type is
       *                TYPE_FORWARD_ONLY.
       */
06912       public boolean last() throws SQLException {
            checkClosed();

            boolean b = true;
            
            if (this.rowData.size() == 0) {
                  b = false;
            } else {

                  if (this.onInsertRow) {
                        this.onInsertRow = false;
                  }
      
                  if (this.doingUpdates) {
                        this.doingUpdates = false;
                  }
      
                  if (this.thisRow != null) {
                        this.thisRow.closeOpenStreams();
                  }
                  
                  this.rowData.beforeLast();
                  this.thisRow = this.rowData.next();
            }

            setRowPositionValidity();
            
            return b;
      }

      // /////////////////////////////////////////
      //
      // These number conversion routines save
      // a ton of "new()s", especially for the heavily
      // used getInt() and getDouble() methods
      //
      // /////////////////////////////////////////

      /**
       * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
       * current row. Has no effect unless the cursor is on the insert row.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or the result set is
       *                not updatable
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
06960       public void moveToCurrentRow() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Move to the insert row. The current cursor position is
       * remembered while the cursor is positioned on the insert row. The insert
       * row is a special row associated with an updatable result set. It is
       * essentially a buffer where a new row may be constructed by calling the
       * updateXXX() methods prior to inserting the row into the result set. Only
       * the updateXXX(), getXXX(), and insertRow() methods may be called when the
       * cursor is on the insert row. All of the columns in a result set must be
       * given a value each time this method is called before calling insertRow().
       * UpdateXXX()must be called before getXXX() on a column.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or the result set is
       *                not updatable
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
06981       public void moveToInsertRow() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * A ResultSet is initially positioned before its first row, the first call
       * to next makes the first row the current row; the second call makes the
       * second row the current row, etc.
       * 
       * <p>
       * If an input stream from the previous row is open, it is implicitly
       * closed. The ResultSet's warning chain is cleared when a new row is read
       * </p>
       * 
       * @return true if the new current is valid; false if there are no more rows
       * 
       * @exception SQLException
       *                if a database access error occurs
       */
07000       public boolean next() throws SQLException {
            checkClosed();

            if (this.onInsertRow) {
                  this.onInsertRow = false;
            }

            if (this.doingUpdates) {
                  this.doingUpdates = false;
            }

            boolean b;

            if (!reallyResult()) {
                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.ResultSet_is_from_UPDATE._No_Data_115"),
                              SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
            }

            if (this.thisRow != null) {
                  this.thisRow.closeOpenStreams();
            }
            
            if (this.rowData.size() == 0) {
                  b = false;
            } else {
                  this.thisRow = this.rowData.next();
                  
                  if (this.thisRow == null) {
                        b = false;
                  } else {
                        clearWarnings();
                        
                        b = true;
                        
                  }
            }

            setRowPositionValidity();
            
            return b;
      }

      private int parseIntAsDouble(int columnIndex, String val)
                  throws NumberFormatException, SQLException {
            if (val == null) {
                  return 0;
            }

            double valueAsDouble = Double.parseDouble(val);

            if (this.jdbcCompliantTruncationForReads) {
                  if (valueAsDouble < Integer.MIN_VALUE
                              || valueAsDouble > Integer.MAX_VALUE) {
                        throwRangeException(String.valueOf(valueAsDouble), columnIndex,
                                    Types.INTEGER);
                  }
            }

            return (int) valueAsDouble;
      }

      private int getIntWithOverflowCheck(int columnIndex) throws SQLException {
            int intValue = this.thisRow.getInt(columnIndex);

            checkForIntegerTruncation(columnIndex + 1 /* only reported in errors */, 
                        null, this.thisRow.getString(
                        columnIndex, this.fields[columnIndex].getCharacterSet(),
                        this.connection), intValue);

            return intValue;
      }
      
      private void checkForIntegerTruncation(int columnIndex,
                  byte[] valueAsBytes, String valueAsString, int intValue)
                  throws SQLException {
            if (this.jdbcCompliantTruncationForReads) {
                  if (intValue == Integer.MIN_VALUE || intValue == Integer.MAX_VALUE) {
                        long valueAsLong = Long
                                    .parseLong(valueAsString == null ? new String(
                                                valueAsBytes) : valueAsString);

                        if (valueAsLong < Integer.MIN_VALUE
                                    || valueAsLong > Integer.MAX_VALUE) {
                              throwRangeException(valueAsString == null ? new String(
                                          valueAsBytes) : valueAsString, columnIndex,
                                          Types.INTEGER);
                        }
                  }
            }
      }

      private long parseLongAsDouble(int columnIndex, String val)
                  throws NumberFormatException, SQLException {
            if (val == null) {
                  return 0;
            }

            double valueAsDouble = Double.parseDouble(val);

            if (this.jdbcCompliantTruncationForReads) {
                  if (valueAsDouble < Long.MIN_VALUE
                              || valueAsDouble > Long.MAX_VALUE) {
                        throwRangeException(val, columnIndex, Types.BIGINT);
                  }
            }

            return (long) valueAsDouble;
      }

      private long getLongWithOverflowCheck(int columnIndex, boolean doOverflowCheck) throws SQLException {
            long longValue = this.thisRow.getLong(columnIndex);

            if (doOverflowCheck) {
                  checkForLongTruncation(columnIndex + 1 /* only reported in errors */, 
                              null, this.thisRow.getString(
                              columnIndex, this.fields[columnIndex].getCharacterSet(),
                              this.connection), longValue);
            }

            return longValue;
      }
      
      private long parseLongWithOverflowCheck(int columnIndex,
                  byte[] valueAsBytes, String valueAsString, boolean doCheck)
                  throws NumberFormatException, SQLException {

            long longValue = 0;

            if (valueAsBytes == null && valueAsString == null) {
                  return 0;
            }

            if (valueAsBytes != null) {
                  longValue = StringUtils.getLong(valueAsBytes);
            } else {
                  //
                  // JDK-6 doesn't like trailing whitespace
                  //
                  // Note this isn't a performance issue, other
                  // than the iteration over the string, as String.trim()
                  // will return a new string only if whitespace is present
                  //
                  
                  valueAsString = valueAsString.trim();
                  
                  longValue = Long.parseLong(valueAsString);
            }

            if (doCheck && this.jdbcCompliantTruncationForReads) {
                  checkForLongTruncation(columnIndex, valueAsBytes, valueAsString,
                              longValue);
            }

            return longValue;
      }

      private void checkForLongTruncation(int columnIndex, byte[] valueAsBytes,
                  String valueAsString, long longValue) throws SQLException {
            if (longValue == Long.MIN_VALUE
                        || longValue == Long.MAX_VALUE) {
                  double valueAsDouble = Double
                              .parseDouble(valueAsString == null ? new String(
                                          valueAsBytes) : valueAsString);

                  if (valueAsDouble < Long.MIN_VALUE
                              || valueAsDouble > Long.MAX_VALUE) {
                        throwRangeException(valueAsString == null ? new String(
                                    valueAsBytes) : valueAsString, columnIndex,
                                    Types.BIGINT);
                  }
            }
      }

      private short parseShortAsDouble(int columnIndex, String val)
                  throws NumberFormatException, SQLException {
            if (val == null) {
                  return 0;
            }

            double valueAsDouble = Double.parseDouble(val);

            if (this.jdbcCompliantTruncationForReads) {
                  if (valueAsDouble < Short.MIN_VALUE
                              || valueAsDouble > Short.MAX_VALUE) {
                        throwRangeException(String.valueOf(valueAsDouble), columnIndex,
                                    Types.SMALLINT);
                  }
            }

            return (short) valueAsDouble;
      }

      private short parseShortWithOverflowCheck(int columnIndex,
                  byte[] valueAsBytes, String valueAsString)
                  throws NumberFormatException, SQLException {

            short shortValue = 0;

            if (valueAsBytes == null && valueAsString == null) {
                  return 0;
            }

            if (valueAsBytes != null) {
                  shortValue = StringUtils.getShort(valueAsBytes);
            } else {
                  //
                  // JDK-6 doesn't like trailing whitespace
                  //
                  // Note this isn't a performance issue, other
                  // than the iteration over the string, as String.trim()
                  // will return a new string only if whitespace is present
                  //
                  
                  valueAsString = valueAsString.trim();
            
                  shortValue = Short.parseShort(valueAsString);
            }

            if (this.jdbcCompliantTruncationForReads) {
                  if (shortValue == Short.MIN_VALUE || shortValue == Short.MAX_VALUE) {
                        long valueAsLong = Long
                                    .parseLong(valueAsString == null ? new String(
                                                valueAsBytes) : valueAsString);

                        if (valueAsLong < Short.MIN_VALUE
                                    || valueAsLong > Short.MAX_VALUE) {
                              throwRangeException(valueAsString == null ? new String(
                                          valueAsBytes) : valueAsString, columnIndex,
                                          Types.SMALLINT);
                        }
                  }
            }

            return shortValue;
      }

      // --------------------------JDBC 2.0-----------------------------------
      // ---------------------------------------------------------------------
      // Getter's and Setter's
      // ---------------------------------------------------------------------

      /**
       * The prev method is not part of JDBC, but because of the architecture of
       * this driver it is possible to move both forward and backward within the
       * result set.
       * 
       * <p>
       * If an input stream from the previous row is open, it is implicitly
       * closed. The ResultSet's warning chain is cleared when a new row is read
       * </p>
       * 
       * @return true if the new current is valid; false if there are no more rows
       * 
       * @exception java.sql.SQLException
       *                if a database access error occurs
       */
07258       public boolean prev() throws java.sql.SQLException {
            checkClosed();

            int rowIndex = this.rowData.getCurrentRowNumber();

            if (this.thisRow != null) {
                  this.thisRow.closeOpenStreams();
            }
            
            boolean b = true;
            
            if ((rowIndex - 1) >= 0) {
                  rowIndex--;
                  this.rowData.setCurrentRow(rowIndex);
                  this.thisRow = this.rowData.getAt(rowIndex);

                  b = true;
            } else if ((rowIndex - 1) == -1) {
                  rowIndex--;
                  this.rowData.setCurrentRow(rowIndex);
                  this.thisRow = null;

                  b = false;
            } else {
                  b = false;
            }
            
            setRowPositionValidity();
            
            return b;
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Moves to the previous row in the result set.
       * </p>
       * 
       * <p>
       * Note: previous() is not the same as relative(-1) since it makes sense to
       * call previous() when there is no current row.
       * </p>
       * 
       * @return true if on a valid row, false if off the result set.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or result set type is
       *                TYPE_FORWAR_DONLY.
       */
07308       public boolean previous() throws SQLException {
            if (this.onInsertRow) {
                  this.onInsertRow = false;
            }

            if (this.doingUpdates) {
                  this.doingUpdates = false;
            }

            return prev();
      }

      /**
       * Closes this ResultSet and releases resources.
       * 
       * @param calledExplicitly
       *            was this called by close()?
       * 
       * @throws SQLException
       *             if an error occurs
       */
07329       public void realClose(boolean calledExplicitly) throws SQLException {
            if (this.isClosed) {
                  return;
            }

            try {
                  if (this.useUsageAdvisor) {
                        
                        // Report on result set closed by driver instead of application
                        
                        if (!calledExplicitly) {            
                              this.eventSink
                                          .consumeEvent(new ProfilerEvent(
                                                      ProfilerEvent.TYPE_WARN,
                                                      "",
                                                      (this.owningStatement == null) ? "N/A"
                                                                  : this.owningStatement.currentCatalog,
                                                      this.connectionId,
                                                      (this.owningStatement == null) ? (-1)
                                                                  : this.owningStatement.getId(),
                                                      this.resultId,
                                                      System.currentTimeMillis(),
                                                      0,
                                                      Constants.MILLIS_I18N,
                                                      null,
                                                      this.pointOfOrigin,
                                                      Messages
                                                                  .getString("ResultSet.ResultSet_implicitly_closed_by_driver"))); //$NON-NLS-1$
                        }

                        if (this.rowData instanceof RowDataStatic) {
                              
                              // Report on possibly too-large result sets
                              
                              if (this.rowData.size() > this.connection
                                          .getResultSetSizeThreshold()) {
                                    this.eventSink
                                                .consumeEvent(new ProfilerEvent(
                                                            ProfilerEvent.TYPE_WARN,
                                                            "",
                                                            (this.owningStatement == null) ? Messages
                                                                        .getString("ResultSet.N/A_159")
                                                                        : this.owningStatement.currentCatalog, //$NON-NLS-1$
                                                            this.connectionId,
                                                            (this.owningStatement == null) ? (-1)
                                                                        : this.owningStatement.getId(),
                                                            this.resultId,
                                                            System.currentTimeMillis(),
                                                            0,
                                                            Constants.MILLIS_I18N,
                                                            null,
                                                            this.pointOfOrigin,
                                                            Messages
                                                                        .getString(
                                                                                    "ResultSet.Too_Large_Result_Set",
                                                                                    new Object[] {
                                                                                                new Integer(
                                                                                                            this.rowData
                                                                                                                        .size()),
                                                                                                new Integer(
                                                                                                            this.connection
                                                                                                                        .getResultSetSizeThreshold()) })));
                              }
                              
                              if (!isLast() && !isAfterLast() && (this.rowData.size() != 0)) {

                                    this.eventSink
                                                .consumeEvent(new ProfilerEvent(
                                                            ProfilerEvent.TYPE_WARN,
                                                            "",
                                                            (this.owningStatement == null) ? Messages
                                                                        .getString("ResultSet.N/A_159")
                                                                        : this.owningStatement.currentCatalog, //$NON-NLS-1$
                                                            this.connectionId,
                                                            (this.owningStatement == null) ? (-1)
                                                                        : this.owningStatement.getId(),
                                                            this.resultId,
                                                            System.currentTimeMillis(),
                                                            0,
                                                            Constants.MILLIS_I18N,
                                                            null,
                                                            this.pointOfOrigin,
                                                            Messages
                                                                        .getString(
                                                                                    "ResultSet.Possible_incomplete_traversal_of_result_set", //$NON-NLS-1$
                                                                                    new Object[] {
                                                                                                new Integer(
                                                                                                            getRow()),
                                                                                                new Integer(
                                                                                                            this.rowData
                                                                                                                        .size()) })));
                              }
                        }

                        //
                        // Report on any columns that were selected but
                        // not referenced
                        //
                        
                        if (this.columnUsed.length > 0 && !this.rowData.wasEmpty()) {
                              StringBuffer buf = new StringBuffer(
                                          Messages
                                                      .getString("ResultSet.The_following_columns_were_never_referenced")); //$NON-NLS-1$

                              boolean issueWarn = false;

                              for (int i = 0; i < this.columnUsed.length; i++) {
                                    if (!this.columnUsed[i]) {
                                          if (!issueWarn) {
                                                issueWarn = true;
                                          } else {
                                                buf.append(", ");
                                          }

                                          buf.append(this.fields[i].getFullName());
                                    }
                              }

                              if (issueWarn) {
                                    this.eventSink.consumeEvent(new ProfilerEvent(
                                                ProfilerEvent.TYPE_WARN, "",
                                                (this.owningStatement == null) ? "N/A"
                                                            : this.owningStatement.currentCatalog,
                                                this.connectionId,
                                                (this.owningStatement == null) ? (-1)
                                                            : this.owningStatement.getId(), 0,
                                                System.currentTimeMillis(), 0,
                                                Constants.MILLIS_I18N, null,
                                                this.pointOfOrigin, buf.toString()));
                              }
                        }
                  }
            } finally {
                  SQLException exceptionDuringClose = null;

                  if (this.rowData != null) {
                        try {
                              this.rowData.close();
                        } catch (SQLException sqlEx) {
                              exceptionDuringClose = sqlEx;
                        }
                  }

                  this.rowData = null;
                  this.defaultTimeZone = null;
                  this.fields = null;
                  this.columnNameToIndex = null;
                  this.fullColumnNameToIndex = null;
                  this.eventSink = null;
                  this.warningChain = null;
                  
                  if (!this.retainOwningStatement) {
                        this.owningStatement = null;
                  }
                  
                  this.catalog = null;
                  this.serverInfo = null;
                  this.thisRow = null;
                  this.fastDateCal = null;
                  this.connection = null;

                  this.isClosed = true;

                  if (exceptionDuringClose != null) {
                        throw exceptionDuringClose;
                  }
            }
      }

07498       public boolean reallyResult() {
            if (this.rowData != null) {
                  return true;
            }

            return this.reallyResult;
      }

      /**
       * JDBC 2.0 Refresh the value of the current row with its current value in
       * the database. Cannot be called when on the insert row. The refreshRow()
       * method provides a way for an application to explicitly tell the JDBC
       * driver to refetch a row(s) from the database. An application may want to
       * call refreshRow() when caching or prefetching is being done by the JDBC
       * driver to fetch the latest value of a row from the database. The JDBC
       * driver may actually refresh multiple rows at once if the fetch size is
       * greater than one. All values are refetched subject to the transaction
       * isolation level and cursor sensitivity. If refreshRow() is called after
       * calling updateXXX(), but before calling updateRow() then the updates made
       * to the row are lost. Calling refreshRow() frequently will likely slow
       * performance.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or if called when on
       *                the insert row.
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
07526       public void refreshRow() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0
       * 
       * <p>
       * Moves a relative number of rows, either positive or negative. Attempting
       * to move beyond the first/last row in the result set positions the cursor
       * before/after the the first/last row. Calling relative(0) is valid, but
       * does not change the cursor position.
       * </p>
       * 
       * <p>
       * Note: Calling relative(1) is different than calling next() since is makes
       * sense to call next() when there is no current row, for example, when the
       * cursor is positioned before the first row or after the last row of the
       * result set.
       * </p>
       * 
       * @param rows
       *            the number of relative rows to move the cursor.
       * 
       * @return true if on a row, false otherwise.
       * 
       * @throws SQLException
       *             if a database-access error occurs, or there is no current
       *             row, or result set type is TYPE_FORWARD_ONLY.
       */
07556       public boolean relative(int rows) throws SQLException {
            checkClosed();

            if (this.rowData.size() == 0) {
                  setRowPositionValidity();
                  
                  return false;
            }

            if (this.thisRow != null) {
                  this.thisRow.closeOpenStreams();
            }
            
            this.rowData.moveRowRelative(rows);
            this.thisRow = this.rowData.getAt(this.rowData.getCurrentRowNumber());

            setRowPositionValidity();
            
            return (!this.rowData.isAfterLast() && !this.rowData.isBeforeFirst());
      }

      /**
       * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave
       * a visible "hole" in a result set. This method can be used to detect holes
       * in a result set. The value returned depends on whether or not the result
       * set can detect deletions.
       * 
       * @return true if deleted and deletes are detected
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotImplemented
       *             DOCUMENT ME!
       * 
       * @see DatabaseMetaData#deletesAreDetected
       */
07592       public boolean rowDeleted() throws SQLException {
            throw new NotImplemented();
      }

      /**
       * JDBC 2.0 Determine if the current row has been inserted. The value
       * returned depends on whether or not the result set can detect visible
       * inserts.
       * 
       * @return true if inserted and inserts are detected
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotImplemented
       *             DOCUMENT ME!
       * 
       * @see DatabaseMetaData#insertsAreDetected
       */
07610       public boolean rowInserted() throws SQLException {
            throw new NotImplemented();
      }

      /**
       * JDBC 2.0 Determine if the current row has been updated. The value
       * returned depends on whether or not the result set can detect updates.
       * 
       * @return true if the row has been visibly updated by the owner or another,
       *         and updates are detected
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotImplemented
       *             DOCUMENT ME!
       * 
       * @see DatabaseMetaData#updatesAreDetected
       */
07628       public boolean rowUpdated() throws SQLException {
            throw new NotImplemented();
      }

      /**
       * Flag that this result set is 'binary' encoded (from a PreparedStatement),
       * not stored as strings.
       */
07636       protected void setBinaryEncoded() {
            this.isBinaryEncoded = true;
      }

      private void setDefaultTimeZone(TimeZone defaultTimeZone) {
            this.defaultTimeZone = defaultTimeZone;
      }

      /**
       * JDBC 2.0 Give a hint as to the direction in which the rows in this result
       * set will be processed. The initial value is determined by the statement
       * that produced the result set. The fetch direction may be changed at any
       * time.
       * 
       * @param direction
       *            the direction to fetch rows in.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or the result set type
       *                is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
       *                MM.MySQL actually ignores this, because it has the whole
       *                result set anyway, so the direction is immaterial.
       */
07659       public void setFetchDirection(int direction) throws SQLException {
            if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE)
                        && (direction != FETCH_UNKNOWN)) {
                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Illegal_value_for_fetch_direction_64"),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }

            this.fetchDirection = direction;
      }

      /**
       * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should
       * be fetched from the database when more rows are needed for this result
       * set. If the fetch size specified is zero, then the JDBC driver ignores
       * the value, and is free to make its own best guess as to what the fetch
       * size should be. The default value is set by the statement that creates
       * the result set. The fetch size may be changed at any time.
       * 
       * @param rows
       *            the number of rows to fetch
       * 
       * @exception SQLException
       *                if a database-access error occurs, or the condition 0 lteq
       *                rows lteq this.getMaxRows() is not satisfied. Currently
       *                ignored by this driver.
       */
07687       public void setFetchSize(int rows) throws SQLException {
            if (rows < 0) { /* || rows > getMaxRows() */
                  throw SQLError.createSQLException(
                              Messages
                                          .getString("ResultSet.Value_must_be_between_0_and_getMaxRows()_66"), //$NON-NLS-1$
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
            }

            this.fetchSize = rows;
      }

      /**
       * Sets the first character of the query that this result set was created
       * from.
       * 
       * @param c
       *            the first character of the query...uppercased
       */
07705       public void setFirstCharOfQuery(char c) {
            this.firstCharOfQuery = c;
      }

      /**
       * DOCUMENT ME!
       * 
       * @param nextResultSet
       *            Sets the next result set in the result set chain for multiple
       *            result sets.
       */
07716       protected void setNextResultSet(ResultSetInternalMethods nextResultSet) {
            this.nextResultSet = nextResultSet;
      }

07720       public void setOwningStatement(com.mysql.jdbc.StatementImpl owningStatement) {
            this.owningStatement = owningStatement;
      }

      /**
       * Sets the concurrency (JDBC2)
       * 
       * @param concurrencyFlag
       *            CONCUR_UPDATABLE or CONCUR_READONLY
       */
07730       protected void setResultSetConcurrency(int concurrencyFlag) {
            this.resultSetConcurrency = concurrencyFlag;
      }

      /**
       * Sets the result set type for (JDBC2)
       * 
       * @param typeFlag
       *            SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support
       *            SCROLL_INSENSITIVE)
       */
07741       protected void setResultSetType(int typeFlag) {
            this.resultSetType = typeFlag;
      }

      /**
       * Sets server info (if any)
       * 
       * @param info
       *            the server info message
       */
07751       protected void setServerInfo(String info) {
            this.serverInfo = info;
      }

      public void setStatementUsedForFetchingRows(PreparedStatement stmt) {
            this.statementUsedForFetchingRows = stmt;
      }

      /**
       * @param wrapperStatement
       *            The wrapperStatement to set.
       */
07763       public void setWrapperStatement(java.sql.Statement wrapperStatement) {
            this.wrapperStatement = wrapperStatement;
      }

      private void throwRangeException(String valueAsString, int columnIndex,
                  int jdbcType) throws SQLException {
            String datatype = null;

            switch (jdbcType) {
            case Types.TINYINT:
                  datatype = "TINYINT";
                  break;
            case Types.SMALLINT:
                  datatype = "SMALLINT";
                  break;
            case Types.INTEGER:
                  datatype = "INTEGER";
                  break;
            case Types.BIGINT:
                  datatype = "BIGINT";
                  break;
            case Types.REAL:
                  datatype = "REAL";
                  break;
            case Types.FLOAT:
                  datatype = "FLOAT";
                  break;
            case Types.DOUBLE:
                  datatype = "DOUBLE";
                  break;
            case Types.DECIMAL:
                  datatype = "DECIMAL";
                  break;
            default:
                  datatype = " (JDBC type '" + jdbcType + "')";
            }

            throw SQLError.createSQLException("'" + valueAsString + "' in column '"
                        + columnIndex + "' is outside valid range for the datatype "
                        + datatype + ".", SQLError.SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE);
      }

      /**
       * DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       */
07810       public String toString() {
            if (this.reallyResult) {
                  return super.toString();
            }

            return "Result set representing update count of " + this.updateCount;
      }

      /**
       * @see ResultSetInternalMethods#updateArray(int, Array)
       */
07821       public void updateArray(int arg0, Array arg1) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * @see ResultSetInternalMethods#updateArray(String, Array)
       */
07828       public void updateArray(String arg0, Array arg1) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
       * methods are used to update column values in the current row, or the
       * insert row. The updateXXX() methods do not update the underlying
       * database, instead the updateRow() or insertRow() methods are called to
       * update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * @param length
       *            the length of the stream
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
07851       public void updateAsciiStream(int columnIndex, java.io.InputStream x,
                  int length) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
       * methods are used to update column values in the current row, or the
       * insert row. The updateXXX() methods do not update the underlying
       * database, instead the updateRow() or insertRow() methods are called to
       * update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * @param length
       *            of the stream
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
07873       public void updateAsciiStream(String columnName, java.io.InputStream x,
                  int length) throws SQLException {
            updateAsciiStream(findColumn(columnName), x, length);
      }

      /**
       * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
07894       public void updateBigDecimal(int columnIndex, BigDecimal x)
                  throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
07913       public void updateBigDecimal(String columnName, BigDecimal x)
                  throws SQLException {
            updateBigDecimal(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
       * methods are used to update column values in the current row, or the
       * insert row. The updateXXX() methods do not update the underlying
       * database, instead the updateRow() or insertRow() methods are called to
       * update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * @param length
       *            the length of the stream
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
07937       public void updateBinaryStream(int columnIndex, java.io.InputStream x,
                  int length) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
       * methods are used to update column values in the current row, or the
       * insert row. The updateXXX() methods do not update the underlying
       * database, instead the updateRow() or insertRow() methods are called to
       * update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * @param length
       *            of the stream
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
07959       public void updateBinaryStream(String columnName, java.io.InputStream x,
                  int length) throws SQLException {
            updateBinaryStream(findColumn(columnName), x, length);
      }

      /**
       * @see ResultSetInternalMethods#updateBlob(int, Blob)
       */
07967       public void updateBlob(int arg0, java.sql.Blob arg1) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * @see ResultSetInternalMethods#updateBlob(String, Blob)
       */
07974       public void updateBlob(String arg0, java.sql.Blob arg1) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
07994       public void updateBoolean(int columnIndex, boolean x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08012       public void updateBoolean(String columnName, boolean x) throws SQLException {
            updateBoolean(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08032       public void updateByte(int columnIndex, byte x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08050       public void updateByte(String columnName, byte x) throws SQLException {
            updateByte(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08070       public void updateBytes(int columnIndex, byte[] x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08088       public void updateBytes(String columnName, byte[] x) throws SQLException {
            updateBytes(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a character stream value. The updateXXX()
       * methods are used to update column values in the current row, or the
       * insert row. The updateXXX() methods do not update the underlying
       * database, instead the updateRow() or insertRow() methods are called to
       * update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * @param length
       *            the length of the stream
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08111       public void updateCharacterStream(int columnIndex, java.io.Reader x,
                  int length) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a character stream value. The updateXXX()
       * methods are used to update column values in the current row, or the
       * insert row. The updateXXX() methods do not update the underlying
       * database, instead the updateRow() or insertRow() methods are called to
       * update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param reader
       *            the stream to update the column with
       * @param length
       *            of the stream
       * 
       * @throws SQLException
       *             if a database-access error occurs
       */
08133       public void updateCharacterStream(String columnName, java.io.Reader reader,
                  int length) throws SQLException {
            updateCharacterStream(findColumn(columnName), reader, length);
      }

      /**
       * @see ResultSetInternalMethods#updateClob(int, Clob)
       */
08141       public void updateClob(int arg0, java.sql.Clob arg1) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * @see ResultSetInternalMethods#updateClob(String, Clob)
       */
08148       public void updateClob(String columnName, java.sql.Clob clob)
                  throws SQLException {
            updateClob(findColumn(columnName), clob);
      }

      /**
       * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08169       public void updateDate(int columnIndex, java.sql.Date x)
                  throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08188       public void updateDate(String columnName, java.sql.Date x)
                  throws SQLException {
            updateDate(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08209       public void updateDouble(int columnIndex, double x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08227       public void updateDouble(String columnName, double x) throws SQLException {
            updateDouble(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08247       public void updateFloat(int columnIndex, float x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08265       public void updateFloat(String columnName, float x) throws SQLException {
            updateFloat(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08285       public void updateInt(int columnIndex, int x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08303       public void updateInt(String columnName, int x) throws SQLException {
            updateInt(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08323       public void updateLong(int columnIndex, long x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08341       public void updateLong(String columnName, long x) throws SQLException {
            updateLong(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08359       public void updateNull(int columnIndex) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08375       public void updateNull(String columnName) throws SQLException {
            updateNull(findColumn(columnName));
      }

      /**
       * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08395       public void updateObject(int columnIndex, Object x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * @param scale
       *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
       *            this is the number of digits after the decimal. For all other
       *            types this value will be ignored.
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08419       public void updateObject(int columnIndex, Object x, int scale)
                  throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08438       public void updateObject(String columnName, Object x) throws SQLException {
            updateObject(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * @param scale
       *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
       *            this is the number of digits after the decimal. For all other
       *            types this value will be ignored.
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08460       public void updateObject(String columnName, Object x, int scale)
                  throws SQLException {
            updateObject(findColumn(columnName), x);
      }

      /**
       * @see ResultSetInternalMethods#updateRef(int, Ref)
       */
08468       public void updateRef(int arg0, Ref arg1) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * @see ResultSetInternalMethods#updateRef(String, Ref)
       */
08475       public void updateRef(String arg0, Ref arg1) throws SQLException {
            throw new NotImplemented();
      }

      /**
       * JDBC 2.0 Update the underlying database with the new contents of the
       * current row. Cannot be called when on the insert row.
       * 
       * @exception SQLException
       *                if a database-access error occurs, or if called when on
       *                the insert row
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08489       public void updateRow() throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08509       public void updateShort(int columnIndex, short x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08527       public void updateShort(String columnName, short x) throws SQLException {
            updateShort(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08547       public void updateString(int columnIndex, String x) throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08565       public void updateString(String columnName, String x) throws SQLException {
            updateString(findColumn(columnName), x);
      }

      /**
       * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08585       public void updateTime(int columnIndex, java.sql.Time x)
                  throws SQLException {
            throw new NotUpdatable();
      }

      /**
       * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
       * used to update column values in the current row, or the insert row. The
       * updateXXX() methods do not update the underlying database, instead the
       * updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08604       public void updateTime(String columnName, java.sql.Time x)
                  throws SQLException {
            updateTime(findColumn(columnName), x);
      }

      
      /**
       * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnIndex
       *            the first column is 1, the second is 2, ...
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       * @throws NotUpdatable
       *             DOCUMENT ME!
       */
08626       public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
                  throws SQLException {
            throw new NotUpdatable();
      }
      
      /**
       * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
       * are used to update column values in the current row, or the insert row.
       * The updateXXX() methods do not update the underlying database, instead
       * the updateRow() or insertRow() methods are called to update the database.
       * 
       * @param columnName
       *            the name of the column
       * @param x
       *            the new column value
       * 
       * @exception SQLException
       *                if a database-access error occurs
       */
08645       public void updateTimestamp(String columnName, java.sql.Timestamp x)
                  throws SQLException {
            updateTimestamp(findColumn(columnName), x);
      }

      /**
       * A column may have the value of SQL NULL; wasNull() reports whether the
       * last column read had this special value. Note that you must first call
       * getXXX on a column to try to read its value and then call wasNull() to
       * find if the value was SQL NULL
       * 
       * @return true if the last column read was SQL NULL
       * 
       * @exception SQLException
       *                if a database access error occurred
       */
08661       public boolean wasNull() throws SQLException {
            return this.wasNullFlag;
      }

      protected Calendar getGmtCalendar() {
            
            // Worst case we allocate this twice and the other gets GC'd,
            // however prevents deadlock
            if (this.gmtCalendar == null) {
                  this.gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
            }
            
            return this.gmtCalendar;
      }
}

Generated by  Doxygen 1.6.0   Back to index