/** * @param columnIndex * @param bits * @param offset * @param length * @param targetCalendar * @param tz * @param rollForward * @param conn * @param rs * @return * @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; } }
protected Time getTimeFast( int columnIndex, byte[] timeAsBytes, int offset, int fullLength, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs) throws SQLException { int hr = 0; int min = 0; int sec = 0; int nanos = 0; int decimalIndex = -1; try { if (timeAsBytes == null) { return null; } boolean allZeroTime = true; boolean onlyTimePresent = false; for (int i = 0; i < fullLength; i++) { if (timeAsBytes[offset + i] == ':') { onlyTimePresent = true; break; } } for (int i = 0; i < fullLength; i++) { if (timeAsBytes[offset + i] == '.') { decimalIndex = i; break; } } for (int i = 0; i < fullLength; 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 '" + StringUtils.toString(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]; int length = fullLength; if (decimalIndex != -1) { length = decimalIndex; if ((decimalIndex + 2) <= fullLength) { nanos = StringUtils.getInt(timeAsBytes, offset + decimalIndex + 1, offset + fullLength); int numDigits = (fullLength) - (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 } } 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 */ @SuppressWarnings("unused") 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); @SuppressWarnings("unused") 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$ + StringUtils.toString(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) { // TODO: return rs.fastTimeCreate(targetCalendar, hr, min, sec, nanos); // java.sql.Time doesn't contain fractional part, so PreparedStatement.setTime/getTime can't // deal with TIME(n) fractional part. // There may be better mappings to high-precision time coming in JDBC-5 with the adoption of // JSR-310. 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); // TODO: min, sec, nanos), conn.getServerTimezoneTZ(), tz, // java.sql.Time doesn't contain fractional part, so PreparedStatement.setTime/getTime can't // deal with TIME(n) fractional part. // There may be better mappings to high-precision time coming in JDBC-5 with the adoption of // JSR-310. } } catch (RuntimeException ex) { SQLException sqlEx = SQLError.createSQLException( ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); sqlEx.initCause(ex); throw sqlEx; } }
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; } }
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); } }
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 '" + StringUtils.toString(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 '" + StringUtils.toString(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; } }