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

ResultSetRow.java

/*
 Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 

  The MySQL Connector/J is licensed under the terms of the GPLv2
  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
  There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
  this software, see the FLOSS License Exception
  <http://www.mysql.com/about/legal/licensing/foss-exception.html>.

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

  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., 51 Franklin St, Fifth
  Floor, Boston, MA 02110-1301  USA
 
 */
package com.mysql.jdbc;

import java.io.InputStream;
import java.io.Reader;
import java.sql.Date;
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.StringTokenizer;
import java.util.TimeZone;

/**
 * Classes that implement this interface represent one row of data from the
 * MySQL server that might be stored in different ways depending on whether the
 * result set was streaming (so they wrap a reusable packet), or whether the
 * result set was cached or via a server-side cursor (so they represent a
 * byte[][]).
 * 
 * Notice that <strong>no</strong> bounds checking is expected for implementors
 * of this interface, it happens in ResultSetImpl.
 * 
 * @version $Id: $
 */
00050 public abstract class ResultSetRow {
      protected ExceptionInterceptor exceptionInterceptor;
      
      protected ResultSetRow(ExceptionInterceptor exceptionInterceptor) {
            this.exceptionInterceptor = exceptionInterceptor;
      }
      
      /**
       * The metadata of the fields of this result set.
       */
00060       protected Field[] metadata;

      /**
       * Called during navigation to next row to close all open
       * streams.
       */
      public abstract void closeOpenStreams();

      /**
       * Returns data at the given index as an InputStream with no
       * character conversion.
       * 
       * @param columnIndex
       *            of the column value (starting at 0) to return.
       * @return the value at the given index as an InputStream or null
       *         if null.
       *         
       * @throws SQLException if an error occurs while retrieving the value.
       */
      public abstract InputStream getBinaryInputStream(int columnIndex)
                  throws SQLException;

      /**
       * Returns the value at the given column (index starts at 0) "raw" (i.e.
       * as-returned by the server).
       * 
       * @param index
       *            of the column value (starting at 0) to return.
       * @return the value for the given column (including NULL if it is)
       * @throws SQLException
       *             if an error occurs while retrieving the value.
       */
      public abstract byte[] getColumnValue(int index) throws SQLException;

      protected final java.sql.Date getDateFast(int columnIndex,
                  byte[] dateAsBytes, int offset, int length, MySQLConnection conn,
                  ResultSetImpl rs, Calendar targetCalendar) throws SQLException {

            int year = 0;
            int month = 0;
            int day = 0;

            try {
                  if (dateAsBytes == null) {
                        return null;
                  }

                  boolean allZeroDate = true;

                  boolean onlyTimePresent = false;

                  for (int i = 0; i < length; i++) {
                        if (dateAsBytes[offset + i] == ':') {
                              onlyTimePresent = true;
                              break;
                        }
                  }

                  for (int i = 0; i < length; i++) {
                        byte b = dateAsBytes[offset + i];

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

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

                              break;
                        }
                  }

                  if (!onlyTimePresent && allZeroDate) {

                        if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                    .equals(conn.getZeroDateTimeBehavior())) {

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

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

                  } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
                        // Convert from TIMESTAMP
                        switch (length) {
                        case 29:
                        case 21:
                        case 19: { // java.sql.Timestamp format
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 4);
                              month = StringUtils.getInt(dateAsBytes, offset + 5,
                                          offset + 7);
                              day = StringUtils.getInt(dateAsBytes, offset + 8,
                                          offset + 10);

                              return rs.fastDateCreate(targetCalendar, year, month, day);
                        }

                        case 14:
                        case 8: {
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 4);
                              month = StringUtils.getInt(dateAsBytes, offset + 4,
                                          offset + 6);
                              day = StringUtils.getInt(dateAsBytes, offset + 6,
                                          offset + 8);

                              return rs.fastDateCreate(targetCalendar, year, month, day);
                        }

                        case 12:
                        case 10:
                        case 6: {
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 2);

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

                              month = StringUtils.getInt(dateAsBytes, offset + 2,
                                          offset + 4);
                              day = StringUtils.getInt(dateAsBytes, offset + 4,
                                          offset + 6);

                              return rs.fastDateCreate(targetCalendar, year + 1900, month, day);
                        }

                        case 4: {
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 4);

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

                              month = StringUtils.getInt(dateAsBytes, offset + 2,
                                          offset + 4);

                              return rs.fastDateCreate(targetCalendar, year + 1900, month, 1);
                        }

                        case 2: {
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 2);

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

                              return rs.fastDateCreate(targetCalendar, year + 1900, 1, 1);
                        }

                        default:
                              throw SQLError
                                          .createSQLException(
                                                      Messages
                                                                  .getString(
                                                                              "ResultSet.Bad_format_for_Date",
                                                                              new Object[] {
                                                                                          new String(
                                                                                                      dateAsBytes),
                                                                                          Integer.valueOf(columnIndex + 1) }),
                                                      SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$
                        } /* endswitch */
                  } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {

                        if (length == 2 || length == 1) {
                              year = StringUtils.getInt(dateAsBytes, offset, offset
                                          + length);

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

                              year += 1900;
                        } else {
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 4);
                        }

                        return rs.fastDateCreate(targetCalendar, year, 1, 1);
                  } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
                        return rs.fastDateCreate(targetCalendar, 1970, 1, 1); // Return EPOCH
                  } else {
                        if (length < 10) {
                              if (length == 8) {
                                    return rs.fastDateCreate(targetCalendar, 1970, 1, 1); // Return
                                    // EPOCH for
                                    // TIME
                              }

                              throw SQLError
                                          .createSQLException(
                                                      Messages
                                                                  .getString(
                                                                              "ResultSet.Bad_format_for_Date",
                                                                              new Object[] {
                                                                                          new String(
                                                                                                      dateAsBytes),
                                                                                          Integer.valueOf(columnIndex + 1) }),
                                                      SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$
                        }

                        if (length != 18) {
                              year = StringUtils.getInt(dateAsBytes, offset + 0,
                                          offset + 4);
                              month = StringUtils.getInt(dateAsBytes, offset + 5,
                                          offset + 7);
                              day = StringUtils.getInt(dateAsBytes, offset + 8,
                                          offset + 10);
                        } else {
                              // JDK-1.3 timestamp format, not real easy to parse
                              // positionally :p
                              StringTokenizer st = new StringTokenizer(new String(
                                          dateAsBytes, offset, length, "ISO8859_1"), "- ");

                              year = Integer.parseInt(st.nextToken());
                              month = Integer.parseInt(st.nextToken());
                              day = Integer.parseInt(st.nextToken());
                        }
                  }

                  return rs.fastDateCreate(targetCalendar, year, month, day);
            } catch (SQLException sqlEx) {
                  throw sqlEx; // don't re-wrap
            } catch (Exception e) {
                  SQLException sqlEx = SQLError.createSQLException(Messages.getString(
                              "ResultSet.Bad_format_for_Date", new Object[] {
                                          new String(dateAsBytes),
                                          Integer.valueOf(columnIndex + 1) }),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$
                  sqlEx.initCause(e);
                  
                  throw sqlEx;
            }
      }

      public abstract java.sql.Date getDateFast(int columnIndex,
                  MySQLConnection conn, ResultSetImpl rs, Calendar targetCalendar) throws SQLException;

      /**
       * Returns the value at the given column (index starts at 0) as an int. *
       * 
       * @param index
       *            of the column value (starting at 0) to return.
       * @return the value for the given column (returns 0 if NULL, use isNull()
       *         to determine if the value was actually NULL)
       * @throws SQLException
       *             if an error occurs while retrieving the value.
       */
      public abstract int getInt(int columnIndex) throws SQLException;

      /**
       * Returns the value at the given column (index starts at 0) as a long. *
       * 
       * @param index
       *            of the column value (starting at 0) to return.
       * @return the value for the given column (returns 0 if NULL, use isNull()
       *         to determine if the value was actually NULL)
       * @throws SQLException
       *             if an error occurs while retrieving the value.
       */
      public abstract long getLong(int columnIndex) throws SQLException;

      protected java.sql.Date getNativeDate(int columnIndex, byte[] bits,
                  int offset, int length, MySQLConnection conn, ResultSetImpl rs, Calendar cal)
                  throws SQLException {

            int year = 0;
            int month = 0;
            int day = 0;

            if (length != 0) {
                  year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8);

                  month = bits[offset + 2];
                  day = bits[offset + 3];
            }

            if (length == 0 || ((year == 0) && (month == 0) && (day == 0))) {
                  if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                              .equals(conn.getZeroDateTimeBehavior())) {
                        return null;
                  } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                              .equals(conn.getZeroDateTimeBehavior())) {
                        throw SQLError
                                    .createSQLException(
                                                "Value '0000-00-00' can not be represented as java.sql.Date",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                  }

                  year = 1;
                  month = 1;
                  day = 1;
            }

            if (!rs.useLegacyDatetimeCode) {
                  return TimeUtil.fastDateCreate(year, month, day, cal);
            }
            
            return rs.fastDateCreate(cal == null ? rs.getCalendarInstanceForSessionOrNew() : cal, year,
                        month, day);
      }

      public abstract Date getNativeDate(int columnIndex, MySQLConnection conn,
                  ResultSetImpl rs, Calendar cal) throws SQLException;

      protected Object getNativeDateTimeValue(int columnIndex, byte[] bits,
                  int offset, int length, Calendar targetCalendar, int jdbcType,
                  int mysqlType, TimeZone tz, boolean rollForward, MySQLConnection conn,
                  ResultSetImpl rs) throws SQLException {

            int year = 0;
            int month = 0;
            int day = 0;

            int hour = 0;
            int minute = 0;
            int seconds = 0;

            int nanos = 0;

            if (bits == null) {

                  return null;
            }

            Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
                        .getUtcCalendar()
                        : rs.getCalendarInstanceForSessionOrNew();

            boolean populatedFromDateTimeValue = false;

            switch (mysqlType) {
            case MysqlDefs.FIELD_TYPE_DATETIME:
            case MysqlDefs.FIELD_TYPE_TIMESTAMP:
                  populatedFromDateTimeValue = true;

                  if (length != 0) {
                        year = (bits[offset + 0] & 0xff)
                                    | ((bits[offset + 1] & 0xff) << 8);
                        month = bits[offset + 2];
                        day = bits[offset + 3];

                        if (length > 4) {
                              hour = bits[offset + 4];
                              minute = bits[offset + 5];
                              seconds = bits[offset + 6];
                        }

                        if (length > 7) {
                              // MySQL uses microseconds
                              nanos = ((bits[offset + 7] & 0xff)
                                          | ((bits[offset + 8] & 0xff) << 8)
                                          | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
                        }
                  }

                  break;
            case MysqlDefs.FIELD_TYPE_DATE:
                  populatedFromDateTimeValue = true;

                  if (bits.length != 0) {
                        year = (bits[offset + 0] & 0xff)
                                    | ((bits[offset + 1] & 0xff) << 8);
                        month = bits[offset + 2];
                        day = bits[offset + 3];
                  }

                  break;
            case MysqlDefs.FIELD_TYPE_TIME:
                  populatedFromDateTimeValue = true;

                  if (bits.length != 0) {
                        // bits[0] // skip tm->neg
                        // binaryData.readLong(); // skip daysPart
                        hour = bits[offset + 5];
                        minute = bits[offset + 6];
                        seconds = bits[offset + 7];
                  }

                  year = 1970;
                  month = 1;
                  day = 1;

                  break;
            default:
                  populatedFromDateTimeValue = false;
            }

            switch (jdbcType) {
            case Types.TIME:
                  if (populatedFromDateTimeValue) {
                        if (!rs.useLegacyDatetimeCode) {
                              return TimeUtil.fastTimeCreate(hour, minute, seconds, targetCalendar, this.exceptionInterceptor);
                        }
                        
                        Time time = TimeUtil.fastTimeCreate(rs
                                    .getCalendarInstanceForSessionOrNew(), hour, minute,
                                    seconds, this.exceptionInterceptor);

                        Time adjustedTime = TimeUtil.changeTimezone(conn,
                                    sessionCalendar, targetCalendar, time, conn
                                                .getServerTimezoneTZ(), tz, rollForward);

                        return adjustedTime;
                  }

                  return rs.getNativeTimeViaParseConversion(columnIndex + 1,
                              targetCalendar, tz, rollForward);

            case Types.DATE:
                  if (populatedFromDateTimeValue) {
                        if ((year == 0) && (month == 0) && (day == 0)) {
                              if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                          .equals(conn.getZeroDateTimeBehavior())) {

                                    return null;
                              } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                          .equals(conn.getZeroDateTimeBehavior())) {
                                    throw new SQLException(
                                                "Value '0000-00-00' can not be represented as java.sql.Date",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }

                              year = 1;
                              month = 1;
                              day = 1;
                        }

                        if (!rs.useLegacyDatetimeCode) {
                              return TimeUtil.fastDateCreate(year, month, day, targetCalendar);
                        }
                        
                        return rs
                                    .fastDateCreate(
                                                rs.getCalendarInstanceForSessionOrNew(), year,
                                                month, day);
                  }

                  return rs.getNativeDateViaParseConversion(columnIndex + 1);
            case Types.TIMESTAMP:
                  if (populatedFromDateTimeValue) {
                        if ((year == 0) && (month == 0) && (day == 0)) {
                              if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                          .equals(conn.getZeroDateTimeBehavior())) {

                                    return null;
                              } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                          .equals(conn.getZeroDateTimeBehavior())) {
                                    throw new SQLException(
                                                "Value '0000-00-00' can not be represented as java.sql.Timestamp",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }

                              year = 1;
                              month = 1;
                              day = 1;
                        }

                        if (!rs.useLegacyDatetimeCode) {
                              return TimeUtil.fastTimestampCreate(tz, year, month, day, hour, minute, 
                                          seconds, nanos);
                        }
                        
                        Timestamp ts = rs.fastTimestampCreate(rs
                                    .getCalendarInstanceForSessionOrNew(), year, month,
                                    day, hour, minute, seconds, nanos);

                        Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
                                    sessionCalendar, targetCalendar, ts, conn
                                                .getServerTimezoneTZ(), tz, rollForward);

                        return adjustedTs;
                  }

                  return rs.getNativeTimestampViaParseConversion(columnIndex + 1,
                              targetCalendar, tz, rollForward);

            default:
                  throw new SQLException(
                              "Internal error - conversion method doesn't support this type",
                              SQLError.SQL_STATE_GENERAL_ERROR);
            }
      }

      public abstract Object getNativeDateTimeValue(int columnIndex,
                  Calendar targetCalendar, int jdbcType, int mysqlType,
                  TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs)
                  throws SQLException;

      protected double getNativeDouble(byte[] bits, int offset) {
            long valueAsLong = (bits[offset + 0] & 0xff)
                        | ((long) (bits[offset + 1] & 0xff) << 8)
                        | ((long) (bits[offset + 2] & 0xff) << 16)
                        | ((long) (bits[offset + 3] & 0xff) << 24)
                        | ((long) (bits[offset + 4] & 0xff) << 32)
                        | ((long) (bits[offset + 5] & 0xff) << 40)
                        | ((long) (bits[offset + 6] & 0xff) << 48)
                        | ((long) (bits[offset + 7] & 0xff) << 56);

            return Double.longBitsToDouble(valueAsLong);
      }

      public abstract double getNativeDouble(int columnIndex) throws SQLException;

      protected float getNativeFloat(byte[] bits, int offset) {
            int asInt = (bits[offset + 0] & 0xff)
                        | ((bits[offset + 1] & 0xff) << 8)
                        | ((bits[offset + 2] & 0xff) << 16)
                        | ((bits[offset + 3] & 0xff) << 24);

            return Float.intBitsToFloat(asInt);
      }

      public abstract float getNativeFloat(int columnIndex) throws SQLException;

      protected int getNativeInt(byte[] bits, int offset) {

            int valueAsInt = (bits[offset + 0] & 0xff)
                        | ((bits[offset + 1] & 0xff) << 8)
                        | ((bits[offset + 2] & 0xff) << 16)
                        | ((bits[offset + 3] & 0xff) << 24);

            return valueAsInt;
      }

      public abstract int getNativeInt(int columnIndex) throws SQLException;

      protected long getNativeLong(byte[] bits, int offset) {
            long valueAsLong = (bits[offset + 0] & 0xff)
                        | ((long) (bits[offset + 1] & 0xff) << 8)
                        | ((long) (bits[offset + 2] & 0xff) << 16)
                        | ((long) (bits[offset + 3] & 0xff) << 24)
                        | ((long) (bits[offset + 4] & 0xff) << 32)
                        | ((long) (bits[offset + 5] & 0xff) << 40)
                        | ((long) (bits[offset + 6] & 0xff) << 48)
                        | ((long) (bits[offset + 7] & 0xff) << 56);

            return valueAsLong;
      }

      public abstract long getNativeLong(int columnIndex) throws SQLException;

      protected short getNativeShort(byte[] bits, int offset) {
            short asShort = (short) ((bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8));

            return asShort;
      }

      public abstract short getNativeShort(int columnIndex) throws SQLException;

      protected Time getNativeTime(int columnIndex, byte[] bits, int offset,
                  int length, Calendar targetCalendar, TimeZone tz,
                  boolean rollForward, MySQLConnection conn, ResultSetImpl rs)
                  throws SQLException {

            int hour = 0;
            int minute = 0;
            int seconds = 0;

            if (length != 0) {
                  // bits[0] // skip tm->neg
                  // binaryData.readLong(); // skip daysPart
                  hour = bits[offset + 5];
                  minute = bits[offset + 6];
                  seconds = bits[offset + 7];
            }

            if (!rs.useLegacyDatetimeCode) {
                  return TimeUtil.fastTimeCreate(hour, minute, seconds, targetCalendar, this.exceptionInterceptor);
            }
            
            Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew();

            synchronized (sessionCalendar) {
                  Time time = TimeUtil.fastTimeCreate(sessionCalendar, hour, minute,
                              seconds, this.exceptionInterceptor);

                  Time adjustedTime = TimeUtil.changeTimezone(conn, sessionCalendar,
                              targetCalendar, time, conn.getServerTimezoneTZ(), tz,
                              rollForward);

                  return adjustedTime;
            }
      }

      public abstract Time getNativeTime(int columnIndex,
                  Calendar targetCalendar, TimeZone tz, boolean rollForward,
                  MySQLConnection conn, ResultSetImpl rs) throws SQLException;

      protected Timestamp getNativeTimestamp(byte[] bits, int offset, int length,
                  Calendar targetCalendar, TimeZone tz, boolean rollForward,
                  MySQLConnection conn, ResultSetImpl rs) throws SQLException {
            int year = 0;
            int month = 0;
            int day = 0;

            int hour = 0;
            int minute = 0;
            int seconds = 0;

            int nanos = 0;

            if (length != 0) {
                  year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8);
                  month = bits[offset + 2];
                  day = bits[offset + 3];

                  if (length > 4) {
                        hour = bits[offset + 4];
                        minute = bits[offset + 5];
                        seconds = bits[offset + 6];
                  }

                  if (length > 7) {
                        // MySQL uses microseconds
                        nanos = ((bits[offset + 7] & 0xff)
                                    | ((bits[offset + 8] & 0xff) << 8)
                                    | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
                  }
            }

            if (length == 0 || ((year == 0) && (month == 0) && (day == 0))) {
                  if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                              .equals(conn.getZeroDateTimeBehavior())) {

                        return null;
                  } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                              .equals(conn.getZeroDateTimeBehavior())) {
                        throw SQLError
                                    .createSQLException(
                                                "Value '0000-00-00' can not be represented as java.sql.Timestamp",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                  }

                  year = 1;
                  month = 1;
                  day = 1;
            }

            if (!rs.useLegacyDatetimeCode) {
                  return TimeUtil.fastTimestampCreate(tz, year, month,
                              day, hour, minute, seconds, nanos);
            }
            
            Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
                        .getUtcCalendar()
                        : rs.getCalendarInstanceForSessionOrNew();

            synchronized (sessionCalendar) {
                  Timestamp ts = rs.fastTimestampCreate(sessionCalendar, year, month,
                              day, hour, minute, seconds, nanos);

                  Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
                              sessionCalendar, targetCalendar, ts, conn
                                          .getServerTimezoneTZ(), tz, rollForward);

                  return adjustedTs;
            }
      }

      public abstract Timestamp getNativeTimestamp(int columnIndex,
                  Calendar targetCalendar, TimeZone tz, boolean rollForward,
                  MySQLConnection conn, ResultSetImpl rs) throws SQLException;

      public abstract Reader getReader(int columnIndex) throws SQLException;

      /**
       * Returns the value at the given column (index starts at 0) as a
       * java.lang.String with the requested encoding, using the given
       * MySQLConnection to find character converters.
       * 
       * @param index
       *            of the column value (starting at 0) to return.
       * @param encoding
       *            the Java name for the character encoding
       * @param conn
       *            the connection that created this result set row
       * 
       * @return the value for the given column (including NULL if it is) as a
       *         String
       * 
       * @throws SQLException
       *             if an error occurs while retrieving the value.
       */
      public abstract String getString(int index, String encoding,
                  MySQLConnection conn) throws SQLException;

      /**
       * Convenience method for turning a byte[] into a string with the given
       * encoding.
       * 
       * @param encoding
       *            the Java encoding name for the byte[] -> char conversion
       * @param conn
       *            the MySQLConnection that created the result set
       * @param value
       *            the String value as a series of bytes, encoded using
       *            "encoding"
       * @param offset
       *            where to start the decoding
       * @param length
       *            how many bytes to decode
       * 
       * @return the String as decoded from bytes with the given encoding
       * 
       * @throws SQLException
       *             if an error occurs
       */
00780       protected String getString(String encoding, MySQLConnection conn,
                  byte[] value, int offset, int length) throws SQLException {
            String stringVal = null;

            if ((conn != null) && conn.getUseUnicode()) {
                  try {
                        if (encoding == null) {
                              stringVal = new String(value);
                        } else {
                              SingleByteCharsetConverter converter = conn
                                          .getCharsetConverter(encoding);

                              if (converter != null) {
                                    stringVal = converter.toString(value, offset, length);
                              } else {
                                    stringVal = new String(value, offset, length, encoding);
                              }
                        }
                  } catch (java.io.UnsupportedEncodingException E) {
                        throw SQLError
                                    .createSQLException(
                                                Messages
                                                            .getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$
                                                            + encoding + "'.", "0S100", this.exceptionInterceptor);
                  }
            } else {
                  stringVal = StringUtils.toAsciiString(value, offset, length);
            }

            return stringVal;
      }

      protected Time getTimeFast(int columnIndex, byte[] timeAsBytes, int offset,
                  int length, Calendar targetCalendar, TimeZone tz,
                  boolean rollForward, MySQLConnection conn, ResultSetImpl rs)
                  throws SQLException {

            int hr = 0;
            int min = 0;
            int sec = 0;

            try {

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

                  boolean allZeroTime = true;
                  boolean onlyTimePresent = false;

                  for (int i = 0; i < length; i++) {
                        if (timeAsBytes[offset + i] == ':') {
                              onlyTimePresent = true;
                              break;
                        }
                  }

                  for (int i = 0; i < length; i++) {
                        byte b = timeAsBytes[offset + i];

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

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

                              break;
                        }
                  }

                  if (!onlyTimePresent && allZeroTime) {
                        if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
                                    .equals(conn.getZeroDateTimeBehavior())) {
                              return null;
                        } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                    .equals(conn.getZeroDateTimeBehavior())) {
                              throw SQLError.createSQLException("Value '"
                                          + new String(timeAsBytes)
                                          + "' can not be represented as java.sql.Time",
                                          SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                        }

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

                  Field timeColField = this.metadata[columnIndex];

                  if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {

                        switch (length) {
                        case 19: { // YYYY-MM-DD hh:mm:ss

                              hr = StringUtils.getInt(timeAsBytes, offset + length - 8,
                                          offset + length - 6);
                              min = StringUtils.getInt(timeAsBytes, offset + length - 5,
                                          offset + length - 3);
                              sec = StringUtils.getInt(timeAsBytes, offset + length - 2,
                                          offset + length);
                        }

                              break;
                        case 14:
                        case 12: {
                              hr = StringUtils.getInt(timeAsBytes, offset + length - 6,
                                          offset + length - 4);
                              min = StringUtils.getInt(timeAsBytes, offset + length - 4,
                                          offset + length - 2);
                              sec = StringUtils.getInt(timeAsBytes, offset + length - 2,
                                          offset + length);
                        }

                              break;

                        case 10: {
                              hr = StringUtils
                                          .getInt(timeAsBytes, offset + 6, offset + 8);
                              min = StringUtils.getInt(timeAsBytes, offset + 8,
                                          offset + 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 + 1)
                                                                  + "("
                                                                  + timeColField + ").",
                                                      SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                        } /* endswitch */

                        SQLWarning precisionLost = new SQLWarning(
                                    Messages
                                                .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
                                                + columnIndex + "(" + timeColField + ").");
                        /*
                         * if (this.warningChain == null) { this.warningChain =
                         * precisionLost; } else {
                         * this.warningChain.setNextWarning(precisionLost); }
                         */
                  } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
                        hr = StringUtils.getInt(timeAsBytes, offset + 11, offset + 13);
                        min = StringUtils.getInt(timeAsBytes, offset + 14, offset + 16);
                        sec = StringUtils.getInt(timeAsBytes, offset + 17, offset + 19);

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

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

                        hr = StringUtils.getInt(timeAsBytes, offset + 0, offset + 2);
                        min = StringUtils.getInt(timeAsBytes, offset + 3, offset + 5);
                        sec = (length == 5) ? 0 : StringUtils.getInt(timeAsBytes,
                                    offset + 6, offset + 8);
                  }

                  Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew();

                  if (!rs.useLegacyDatetimeCode) {
                        return rs.fastTimeCreate(targetCalendar, hr, min, sec);
                  }
                  
                  synchronized (sessionCalendar) {
                        return TimeUtil.changeTimezone(conn, sessionCalendar,
                                    targetCalendar, rs.fastTimeCreate(sessionCalendar, hr,
                                                min, sec), conn.getServerTimezoneTZ(), tz,
                                    rollForward);
                  }
            } catch (RuntimeException ex) {
                  SQLException sqlEx = SQLError.createSQLException(ex.toString(),
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                  sqlEx.initCause(ex);
                  
                  throw sqlEx;
            }
      }

      public abstract Time getTimeFast(int columnIndex, Calendar targetCalendar,
                  TimeZone tz, boolean rollForward, MySQLConnection conn,
                  ResultSetImpl rs) throws SQLException;

      protected Timestamp getTimestampFast(int columnIndex,
                  byte[] timestampAsBytes, int offset, int length,
                  Calendar targetCalendar, TimeZone tz, boolean rollForward,
                  MySQLConnection conn, ResultSetImpl rs) throws SQLException {

            try {
                  Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
                              .getUtcCalendar()
                              : rs.getCalendarInstanceForSessionOrNew();

                  synchronized (sessionCalendar) {
                        boolean allZeroTimestamp = true;

                        boolean onlyTimePresent = false;

                        for (int i = 0; i < length; i++) {
                              if (timestampAsBytes[offset + i] == ':') {
                                    onlyTimePresent = true;
                                    break;
                              }
                        }

                        for (int i = 0; i < length; i++) {
                              byte b = timestampAsBytes[offset + 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(conn.getZeroDateTimeBehavior())) {

                                    return null;
                              } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
                                          .equals(conn.getZeroDateTimeBehavior())) {
                                    throw SQLError
                                                .createSQLException(
                                                            "Value '"
                                                                        + new String(timestampAsBytes)
                                                                        + "' can not be represented as java.sql.Timestamp",
                                                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                              }

                              if (!rs.useLegacyDatetimeCode) {
                                    return TimeUtil.fastTimestampCreate(tz, 1, 1, 1, 0, 0, 0, 0);
                              }
                              // We're left with the case of 'round' to a date Java _can_
                              // represent, which is '0001-01-01'.
                              return rs.fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);

                        } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {

                              if (!rs.useLegacyDatetimeCode) {
                                    return TimeUtil.fastTimestampCreate(tz, StringUtils
                                                .getInt(timestampAsBytes, offset, 4), 1, 1, 0,
                                                0, 0, 0);
                              }
                              
                              return TimeUtil.changeTimezone(conn, sessionCalendar,
                                    targetCalendar, rs.fastTimestampCreate(
                                                sessionCalendar, StringUtils.getInt(
                                                            timestampAsBytes, offset, 4), 1, 1,
                                                0, 0, 0, 0), conn.getServerTimezoneTZ(),
                                    tz, rollForward);
                        } else {
                              if (timestampAsBytes[offset + length - 1] == '.') {
                                    length--;
                              }

                              // Convert from TIMESTAMP or DATE
                              
                              int year = 0;
                              int month = 0;
                              int day = 0;
                              int hour = 0;
                              int minutes = 0;
                              int seconds = 0;
                              int nanos = 0;
                              
                              switch (length) {
                              case 29:
                              case 26:
                              case 25:
                              case 24:
                              case 23:
                              case 22:
                              case 21:
                              case 20:
                              case 19: {
                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 4);
                                    month = StringUtils.getInt(timestampAsBytes,
                                                offset + 5, offset + 7);
                                    day = StringUtils.getInt(timestampAsBytes,
                                                offset + 8, offset + 10);
                                    hour = StringUtils.getInt(timestampAsBytes,
                                                offset + 11, offset + 13);
                                    minutes = StringUtils.getInt(timestampAsBytes,
                                                offset + 14, offset + 16);
                                    seconds = StringUtils.getInt(timestampAsBytes,
                                                offset + 17, offset + 19);

                                    nanos = 0;

                                    if (length > 19) {
                                          int decimalIndex = -1;

                                          for (int i = 0; i < length; i++) {
                                                if (timestampAsBytes[offset + i] == '.') {
                                                      decimalIndex = i;
                                                }
                                          }

                                          if (decimalIndex != -1) {
                                                if ((decimalIndex + 2) <= length) {
                                                      nanos = StringUtils.getInt(
                                                                  timestampAsBytes, offset + decimalIndex + 1,
                                                                  offset + length);
                                                      
                                                      int numDigits = (length) - (decimalIndex + 1);
                                                      
                                                      if (numDigits < 9) {
                                                            int factor = (int)(Math.pow(10, 9 - numDigits));
                                                            nanos = nanos * factor;
                                                      }
                                                } else {
                                                      throw new IllegalArgumentException(); // re-thrown
                                                      // further
                                                      // down
                                                      // with
                                                      // a
                                                      // much better error message
                                                }
                                          }
                                    }

                                    break;
                              }

                              case 14: {
                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 4);
                                    month = StringUtils.getInt(timestampAsBytes,
                                                offset + 4, offset + 6);
                                    day = StringUtils.getInt(timestampAsBytes,
                                                offset + 6, offset + 8);
                                    hour = StringUtils.getInt(timestampAsBytes,
                                                offset + 8, offset + 10);
                                    minutes = StringUtils.getInt(timestampAsBytes,
                                                offset + 10, offset + 12);
                                    seconds = StringUtils.getInt(timestampAsBytes,
                                                offset + 12, offset + 14);

                                    break;
                              }

                              case 12: {
                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 2);

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

                                    month = StringUtils.getInt(timestampAsBytes,
                                                offset + 2, offset + 4);
                                    day = StringUtils.getInt(timestampAsBytes,
                                                offset + 4, offset + 6);
                                    hour = StringUtils.getInt(timestampAsBytes,
                                                offset + 6, offset + 8);
                                    minutes = StringUtils.getInt(timestampAsBytes,
                                                offset + 8, offset + 10);
                                    seconds = StringUtils.getInt(timestampAsBytes,
                                                offset + 10, offset + 12);

                                    break;
                              }

                              case 10: {
                                    boolean hasDash = false;

                                    for (int i = 0; i < length; i++) {
                                          if (timestampAsBytes[offset + i] == '-') {
                                                hasDash = true;
                                                break;
                                          }
                                    }

                                    if ((this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
                                                || hasDash) {
                                          year = StringUtils.getInt(timestampAsBytes,
                                                      offset + 0, offset + 4);
                                          month = StringUtils.getInt(timestampAsBytes,
                                                      offset + 5, offset + 7);
                                          day = StringUtils.getInt(timestampAsBytes,
                                                      offset + 8, offset + 10);
                                          hour = 0;
                                          minutes = 0;
                                    } else {
                                          year = StringUtils.getInt(timestampAsBytes,
                                                      offset + 0, offset + 2);

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

                                          month = StringUtils.getInt(timestampAsBytes,
                                                      offset + 2, offset + 4);
                                          day = StringUtils.getInt(timestampAsBytes,
                                                      offset + 4, offset + 6);
                                          hour = StringUtils.getInt(timestampAsBytes,
                                                      offset + 6, offset + 8);
                                          minutes = StringUtils.getInt(timestampAsBytes,
                                                      offset + 8, offset + 10);

                                          year += 1900; // two-digit year
                                    }

                                    break;
                              }

                              case 8: {
                                    boolean hasColon = false;

                                    for (int i = 0; i < length; i++) {
                                          if (timestampAsBytes[offset + i] == ':') {
                                                hasColon = true;
                                                break;
                                          }
                                    }

                                    if (hasColon) {
                                          hour = StringUtils.getInt(timestampAsBytes,
                                                      offset + 0, offset + 2);
                                          minutes = StringUtils.getInt(timestampAsBytes,
                                                      offset + 3, offset + 5);
                                          seconds = StringUtils.getInt(timestampAsBytes,
                                                      offset + 6, offset + 8);
                                          
                                          year = 1970;
                                          month = 1;
                                          day = 1;

                                          break;
                                    }

                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 4);
                                    month = StringUtils.getInt(timestampAsBytes,
                                                offset + 4, offset + 6);
                                    day = StringUtils.getInt(timestampAsBytes,
                                                offset + 6, offset + 8);

                                    year -= 1900;
                                    month--;
                                    
                                    break;
                              }

                              case 6: {
                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 2);

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

                                    year += 1900;
                                    
                                    month = StringUtils.getInt(timestampAsBytes,
                                                offset + 2, offset + 4);
                                    day = StringUtils.getInt(timestampAsBytes,
                                                offset + 4, offset + 6);

                                    break;
                              }

                              case 4: {
                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 2);

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

                                    month = StringUtils.getInt(timestampAsBytes,
                                                offset + 2, offset + 4);
                                    
                                    day = 1;
                                    
                                    break;
                              }

                              case 2: {
                                    year = StringUtils.getInt(timestampAsBytes,
                                                offset + 0, offset + 2);

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

                                    year += 1900;
                                    month = 1;
                                    day = 1;
                                    
                                    break;
                              }

                              default:
                                    throw new java.sql.SQLException(
                                                "Bad format for Timestamp '"
                                                            + new String(timestampAsBytes)
                                                            + "' in column " + (columnIndex + 1)
                                                            + ".",
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
                              }
                              
                              if (!rs.useLegacyDatetimeCode) {
                                    return TimeUtil.fastTimestampCreate(tz,
                                                year, month,
                                                day, hour, minutes, seconds,
                                                nanos);
                              }
                                    
                              return TimeUtil
                                          .changeTimezone(conn, sessionCalendar,
                                                      targetCalendar, rs.fastTimestampCreate(
                                                                  sessionCalendar, year, month,
                                                                  day, hour, minutes, seconds,
                                                                  nanos), conn
                                                                  .getServerTimezoneTZ(), tz,
                                                      rollForward);
                        }
                  }
            } catch (RuntimeException e) {
                  SQLException sqlEx = SQLError.createSQLException("Cannot convert value '"
                              + getString(columnIndex, "ISO8859_1", conn)
                              + "' from column " + (columnIndex + 1) + " to TIMESTAMP.",
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
                  sqlEx.initCause(e);
                  
                  throw sqlEx;
            }
      }

      public abstract Timestamp getTimestampFast(int columnIndex,
                  Calendar targetCalendar, TimeZone tz, boolean rollForward,
                  MySQLConnection conn, ResultSetImpl rs) throws SQLException;

      /**
       * Could the column value at the given index (which starts at 0) be
       * interpreted as a floating-point number (has +/-/E/e in it)?
       * 
       * @param index
       *            of the column value (starting at 0) to check.
       * 
       * @return true if the column value at the given index looks like it might
       *         be a floating-point number, false if not.
       * 
       * @throws SQLException
       *             if an error occurs
       */
      public abstract boolean isFloatingPointNumber(int index)
                  throws SQLException;

      /**
       * Is the column value at the given index (which starts at 0) NULL?
       * 
       * @param index
       *            of the column value (starting at 0) to check.
       * 
       * @return true if the column value is NULL, false if not.
       * 
       * @throws SQLException
       *             if an error occurs
       */
      public abstract boolean isNull(int index) throws SQLException;

      /**
       * Returns the length of the column at the given index (which starts at 0).
       * 
       * @param index
       *            of the column value (starting at 0) for which to return the
       *            length.
       * @return the length of the requested column, 0 if null (clients of this
       *         interface should use isNull() beforehand to determine status of
       *         NULL values in the column).
       * 
       * @throws SQLException
       */
      public abstract long length(int index) throws SQLException;

      /**
       * Sets the given column value (only works currently with
       * ByteArrayRowHolder).
       * 
       * @param index
       *            index of the column value (starting at 0) to set.
       * @param value
       *            the (raw) value to set
       * 
       * @throws SQLException
       *             if an error occurs, or the concrete RowHolder doesn't support
       *             this operation.
       */
      public abstract void setColumnValue(int index, byte[] value)
                  throws SQLException;

      public ResultSetRow setMetadata(Field[] f) throws SQLException {
            this.metadata = f;
            
            return this;
      }
      
      public abstract int getBytesSize();
}

Generated by  Doxygen 1.6.0   Back to index