0001: /*
0002: Copyright (C) 2007 MySQL AB
0003:
0004: This program is free software; you can redistribute it and/or modify
0005: it under the terms of version 2 of the GNU General Public License as
0006: published by the Free Software Foundation.
0007:
0008: There are special exceptions to the terms and conditions of the GPL
0009: as it is applied to this software. View the full text of the
0010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
0011: software distribution.
0012:
0013: This program is distributed in the hope that it will be useful,
0014: but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0016: GNU General Public License for more details.
0017:
0018: You should have received a copy of the GNU General Public License
0019: along with this program; if not, write to the Free Software
0020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0021:
0022: */
0023: package com.mysql.jdbc;
0024:
0025: import java.io.InputStream;
0026: import java.io.Reader;
0027: import java.sql.Date;
0028: import java.sql.SQLException;
0029: import java.sql.SQLWarning;
0030: import java.sql.Time;
0031: import java.sql.Timestamp;
0032: import java.sql.Types;
0033: import java.util.Calendar;
0034: import java.util.StringTokenizer;
0035: import java.util.TimeZone;
0036:
0037: /**
0038: * Classes that implement this interface represent one row of data from the
0039: * MySQL server that might be stored in different ways depending on whether the
0040: * result set was streaming (so they wrap a reusable packet), or whether the
0041: * result set was cached or via a server-side cursor (so they represent a
0042: * byte[][]).
0043: *
0044: * Notice that <strong>no</strong> bounds checking is expected for implementors
0045: * of this interface, it happens in ResultSetImpl.
0046: *
0047: * @version $Id: $
0048: */
0049: public abstract class ResultSetRow {
0050: /**
0051: * The metadata of the fields of this result set.
0052: */
0053: protected Field[] metadata;
0054:
0055: /**
0056: * Called during navigation to next row to close all open
0057: * streams.
0058: */
0059: public abstract void closeOpenStreams();
0060:
0061: /**
0062: * Returns data at the given index as an InputStream with no
0063: * character conversion.
0064: *
0065: * @param columnIndex
0066: * of the column value (starting at 0) to return.
0067: * @return the value at the given index as an InputStream or null
0068: * if null.
0069: *
0070: * @throws SQLException if an error occurs while retrieving the value.
0071: */
0072: public abstract InputStream getBinaryInputStream(int columnIndex)
0073: throws SQLException;
0074:
0075: /**
0076: * Returns the value at the given column (index starts at 0) "raw" (i.e.
0077: * as-returned by the server).
0078: *
0079: * @param index
0080: * of the column value (starting at 0) to return.
0081: * @return the value for the given column (including NULL if it is)
0082: * @throws SQLException
0083: * if an error occurs while retrieving the value.
0084: */
0085: public abstract byte[] getColumnValue(int index)
0086: throws SQLException;
0087:
0088: protected final java.sql.Date getDateFast(int columnIndex,
0089: byte[] dateAsBytes, int offset, int length,
0090: ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
0091:
0092: int year = 0;
0093: int month = 0;
0094: int day = 0;
0095:
0096: try {
0097: if (dateAsBytes == null) {
0098: return null;
0099: }
0100:
0101: boolean allZeroDate = true;
0102:
0103: boolean onlyTimePresent = false;
0104:
0105: for (int i = 0; i < length; i++) {
0106: if (dateAsBytes[offset + i] == ':') {
0107: onlyTimePresent = true;
0108: break;
0109: }
0110: }
0111:
0112: for (int i = 0; i < length; i++) {
0113: byte b = dateAsBytes[offset + i];
0114:
0115: if (b == ' ' || b == '-' || b == '/') {
0116: onlyTimePresent = false;
0117: }
0118:
0119: if (b != '0' && b != ' ' && b != ':' && b != '-'
0120: && b != '/' && b != '.') {
0121: allZeroDate = false;
0122:
0123: break;
0124: }
0125: }
0126:
0127: if (!onlyTimePresent && allZeroDate) {
0128:
0129: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
0130: .equals(conn.getZeroDateTimeBehavior())) {
0131:
0132: return null;
0133: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
0134: .equals(conn.getZeroDateTimeBehavior())) {
0135: throw SQLError
0136: .createSQLException(
0137: "Value '"
0138: + new String(dateAsBytes)
0139: + "' can not be represented as java.sql.Date",
0140: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0141: }
0142:
0143: // We're left with the case of 'round' to a date Java _can_
0144: // represent, which is '0001-01-01'.
0145: return rs.fastDateCreate(null, 1, 1, 1);
0146:
0147: } else if (this .metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
0148: // Convert from TIMESTAMP
0149: switch (length) {
0150: case 21:
0151: case 19: { // java.sql.Timestamp format
0152: year = StringUtils.getInt(dateAsBytes, offset + 0,
0153: offset + 4);
0154: month = StringUtils.getInt(dateAsBytes, offset + 5,
0155: offset + 7);
0156: day = StringUtils.getInt(dateAsBytes, offset + 8,
0157: offset + 10);
0158:
0159: return rs.fastDateCreate(null, year, month, day);
0160: }
0161:
0162: case 14:
0163: case 8: {
0164: year = StringUtils.getInt(dateAsBytes, offset + 0,
0165: offset + 4);
0166: month = StringUtils.getInt(dateAsBytes, offset + 4,
0167: offset + 6);
0168: day = StringUtils.getInt(dateAsBytes, offset + 6,
0169: offset + 8);
0170:
0171: return rs.fastDateCreate(null, year, month, day);
0172: }
0173:
0174: case 12:
0175: case 10:
0176: case 6: {
0177: year = StringUtils.getInt(dateAsBytes, offset + 0,
0178: offset + 2);
0179:
0180: if (year <= 69) {
0181: year = year + 100;
0182: }
0183:
0184: month = StringUtils.getInt(dateAsBytes, offset + 2,
0185: offset + 4);
0186: day = StringUtils.getInt(dateAsBytes, offset + 4,
0187: offset + 6);
0188:
0189: return rs.fastDateCreate(null, year + 1900, month,
0190: day);
0191: }
0192:
0193: case 4: {
0194: year = StringUtils.getInt(dateAsBytes, offset + 0,
0195: offset + 4);
0196:
0197: if (year <= 69) {
0198: year = year + 100;
0199: }
0200:
0201: month = StringUtils.getInt(dateAsBytes, offset + 2,
0202: offset + 4);
0203:
0204: return rs.fastDateCreate(null, year + 1900, month,
0205: 1);
0206: }
0207:
0208: case 2: {
0209: year = StringUtils.getInt(dateAsBytes, offset + 0,
0210: offset + 2);
0211:
0212: if (year <= 69) {
0213: year = year + 100;
0214: }
0215:
0216: return rs.fastDateCreate(null, year + 1900, 1, 1);
0217: }
0218:
0219: default:
0220: throw SQLError
0221: .createSQLException(
0222: Messages
0223: .getString(
0224: "ResultSet.Bad_format_for_Date",
0225: new Object[] {
0226: new String(
0227: dateAsBytes),
0228: Constants
0229: .integerValueOf(columnIndex + 1) }),
0230: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0231: } /* endswitch */
0232: } else if (this .metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
0233:
0234: if (length == 2 || length == 1) {
0235: year = StringUtils.getInt(dateAsBytes, offset,
0236: offset + length);
0237:
0238: if (year <= 69) {
0239: year = year + 100;
0240: }
0241:
0242: year += 1900;
0243: } else {
0244: year = StringUtils.getInt(dateAsBytes, offset + 0,
0245: offset + 4);
0246: }
0247:
0248: return rs.fastDateCreate(null, year, 1, 1);
0249: } else if (this .metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
0250: return rs.fastDateCreate(null, 1970, 1, 1); // Return EPOCH
0251: } else {
0252: if (length < 10) {
0253: if (length == 8) {
0254: return rs.fastDateCreate(null, 1970, 1, 1); // Return
0255: // EPOCH for
0256: // TIME
0257: }
0258:
0259: throw SQLError
0260: .createSQLException(
0261: Messages
0262: .getString(
0263: "ResultSet.Bad_format_for_Date",
0264: new Object[] {
0265: new String(
0266: dateAsBytes),
0267: Constants
0268: .integerValueOf(columnIndex + 1) }),
0269: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0270: }
0271:
0272: if (length != 18) {
0273: year = StringUtils.getInt(dateAsBytes, offset + 0,
0274: offset + 4);
0275: month = StringUtils.getInt(dateAsBytes, offset + 5,
0276: offset + 7);
0277: day = StringUtils.getInt(dateAsBytes, offset + 8,
0278: offset + 10);
0279: } else {
0280: // JDK-1.3 timestamp format, not real easy to parse
0281: // positionally :p
0282: StringTokenizer st = new StringTokenizer(
0283: new String(dateAsBytes, offset, length,
0284: "ISO8859_1"), "- ");
0285:
0286: year = Integer.parseInt(st.nextToken());
0287: month = Integer.parseInt(st.nextToken());
0288: day = Integer.parseInt(st.nextToken());
0289: }
0290: }
0291:
0292: return rs.fastDateCreate(null, year, month, day);
0293: } catch (SQLException sqlEx) {
0294: throw sqlEx; // don't re-wrap
0295: } catch (Exception e) {
0296: throw SQLError
0297: .createSQLException(
0298: Messages
0299: .getString(
0300: "ResultSet.Bad_format_for_Date",
0301: new Object[] {
0302: new String(
0303: dateAsBytes),
0304: Constants
0305: .integerValueOf(columnIndex + 1) }),
0306: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0307: }
0308: }
0309:
0310: public abstract java.sql.Date getDateFast(int columnIndex,
0311: ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
0312:
0313: /**
0314: * Returns the value at the given column (index starts at 0) as an int. *
0315: *
0316: * @param index
0317: * of the column value (starting at 0) to return.
0318: * @return the value for the given column (returns 0 if NULL, use isNull()
0319: * to determine if the value was actually NULL)
0320: * @throws SQLException
0321: * if an error occurs while retrieving the value.
0322: */
0323: public abstract int getInt(int columnIndex) throws SQLException;
0324:
0325: /**
0326: * Returns the value at the given column (index starts at 0) as a long. *
0327: *
0328: * @param index
0329: * of the column value (starting at 0) to return.
0330: * @return the value for the given column (returns 0 if NULL, use isNull()
0331: * to determine if the value was actually NULL)
0332: * @throws SQLException
0333: * if an error occurs while retrieving the value.
0334: */
0335: public abstract long getLong(int columnIndex) throws SQLException;
0336:
0337: protected java.sql.Date getNativeDate(int columnIndex, byte[] bits,
0338: int offset, int length, ConnectionImpl conn,
0339: ResultSetImpl rs) throws SQLException {
0340:
0341: int year = 0;
0342: int month = 0;
0343: int day = 0;
0344:
0345: if (length != 0) {
0346: year = (bits[offset + 0] & 0xff)
0347: | ((bits[offset + 1] & 0xff) << 8);
0348:
0349: month = bits[offset + 2];
0350: day = bits[offset + 3];
0351: }
0352:
0353: if ((year == 0) && (month == 0) && (day == 0)) {
0354: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
0355: .equals(conn.getZeroDateTimeBehavior())) {
0356: return null;
0357: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
0358: .equals(conn.getZeroDateTimeBehavior())) {
0359: throw SQLError
0360: .createSQLException(
0361: "Value '0000-00-00' can not be represented as java.sql.Date",
0362: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0363: }
0364:
0365: year = 1;
0366: month = 1;
0367: day = 1;
0368: }
0369:
0370: return rs
0371: .fastDateCreate(
0372: rs.getCalendarInstanceForSessionOrNew(), year,
0373: month, day);
0374: }
0375:
0376: public abstract Date getNativeDate(int columnIndex,
0377: ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
0378:
0379: protected Object getNativeDateTimeValue(int columnIndex,
0380: byte[] bits, int offset, int length,
0381: Calendar targetCalendar, int jdbcType, int mysqlType,
0382: TimeZone tz, boolean rollForward, ConnectionImpl conn,
0383: ResultSetImpl rs) throws SQLException {
0384:
0385: int year = 0;
0386: int month = 0;
0387: int day = 0;
0388:
0389: int hour = 0;
0390: int minute = 0;
0391: int seconds = 0;
0392:
0393: int nanos = 0;
0394:
0395: if (bits == null) {
0396:
0397: return null;
0398: }
0399:
0400: Calendar sessionCalendar = conn
0401: .getUseJDBCCompliantTimezoneShift() ? conn
0402: .getUtcCalendar() : rs
0403: .getCalendarInstanceForSessionOrNew();
0404:
0405: boolean populatedFromDateTimeValue = false;
0406:
0407: switch (mysqlType) {
0408: case MysqlDefs.FIELD_TYPE_DATETIME:
0409: case MysqlDefs.FIELD_TYPE_TIMESTAMP:
0410: populatedFromDateTimeValue = true;
0411:
0412: if (length != 0) {
0413: year = (bits[offset + 0] & 0xff)
0414: | ((bits[offset + 1] & 0xff) << 8);
0415: month = bits[offset + 2];
0416: day = bits[offset + 3];
0417:
0418: if (length > 4) {
0419: hour = bits[offset + 4];
0420: minute = bits[offset + 5];
0421: seconds = bits[offset + 6];
0422: }
0423:
0424: if (length > 7) {
0425: // MySQL uses microseconds
0426: nanos = ((bits[offset + 7] & 0xff)
0427: | ((bits[offset + 8] & 0xff) << 8)
0428: | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
0429: }
0430: }
0431:
0432: break;
0433: case MysqlDefs.FIELD_TYPE_DATE:
0434: populatedFromDateTimeValue = true;
0435:
0436: if (bits.length != 0) {
0437: year = (bits[offset + 0] & 0xff)
0438: | ((bits[offset + 1] & 0xff) << 8);
0439: month = bits[offset + 2];
0440: day = bits[offset + 3];
0441: }
0442:
0443: break;
0444: case MysqlDefs.FIELD_TYPE_TIME:
0445: populatedFromDateTimeValue = true;
0446:
0447: if (bits.length != 0) {
0448: // bits[0] // skip tm->neg
0449: // binaryData.readLong(); // skip daysPart
0450: hour = bits[offset + 5];
0451: minute = bits[offset + 6];
0452: seconds = bits[offset + 7];
0453: }
0454:
0455: year = 1970;
0456: month = 1;
0457: day = 1;
0458:
0459: break;
0460: default:
0461: populatedFromDateTimeValue = false;
0462: }
0463:
0464: switch (jdbcType) {
0465: case Types.TIME:
0466: if (populatedFromDateTimeValue) {
0467: Time time = TimeUtil.fastTimeCreate(rs
0468: .getCalendarInstanceForSessionOrNew(), hour,
0469: minute, seconds);
0470:
0471: Time adjustedTime = TimeUtil
0472: .changeTimezone(conn, sessionCalendar,
0473: targetCalendar, time, conn
0474: .getServerTimezoneTZ(), tz,
0475: rollForward);
0476:
0477: return adjustedTime;
0478: }
0479:
0480: return rs.getNativeTimeViaParseConversion(columnIndex + 1,
0481: targetCalendar, tz, rollForward);
0482:
0483: case Types.DATE:
0484: if (populatedFromDateTimeValue) {
0485: if ((year == 0) && (month == 0) && (day == 0)) {
0486: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
0487: .equals(conn.getZeroDateTimeBehavior())) {
0488:
0489: return null;
0490: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
0491: .equals(conn.getZeroDateTimeBehavior())) {
0492: throw new SQLException(
0493: "Value '0000-00-00' can not be represented as java.sql.Date",
0494: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0495: }
0496:
0497: year = 1;
0498: month = 1;
0499: day = 1;
0500: }
0501:
0502: return rs.fastDateCreate(rs
0503: .getCalendarInstanceForSessionOrNew(), year,
0504: month, day);
0505: }
0506:
0507: return rs.getNativeDateViaParseConversion(columnIndex + 1);
0508: case Types.TIMESTAMP:
0509: if (populatedFromDateTimeValue) {
0510: if ((year == 0) && (month == 0) && (day == 0)) {
0511: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
0512: .equals(conn.getZeroDateTimeBehavior())) {
0513:
0514: return null;
0515: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
0516: .equals(conn.getZeroDateTimeBehavior())) {
0517: throw new SQLException(
0518: "Value '0000-00-00' can not be represented as java.sql.Timestamp",
0519: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0520: }
0521:
0522: year = 1;
0523: month = 1;
0524: day = 1;
0525: }
0526:
0527: Timestamp ts = rs.fastTimestampCreate(rs
0528: .getCalendarInstanceForSessionOrNew(), year,
0529: month, day, hour, minute, seconds, nanos);
0530:
0531: Timestamp adjustedTs = TimeUtil
0532: .changeTimezone(conn, sessionCalendar,
0533: targetCalendar, ts, conn
0534: .getServerTimezoneTZ(), tz,
0535: rollForward);
0536:
0537: return adjustedTs;
0538: }
0539:
0540: return rs.getNativeTimestampViaParseConversion(
0541: columnIndex + 1, targetCalendar, tz, rollForward);
0542:
0543: default:
0544: throw new SQLException(
0545: "Internal error - conversion method doesn't support this type",
0546: SQLError.SQL_STATE_GENERAL_ERROR);
0547: }
0548: }
0549:
0550: public abstract Object getNativeDateTimeValue(int columnIndex,
0551: Calendar targetCalendar, int jdbcType, int mysqlType,
0552: TimeZone tz, boolean rollForward, ConnectionImpl conn,
0553: ResultSetImpl rs) throws SQLException;
0554:
0555: protected double getNativeDouble(byte[] bits, int offset) {
0556: long valueAsLong = (bits[offset + 0] & 0xff)
0557: | ((long) (bits[offset + 1] & 0xff) << 8)
0558: | ((long) (bits[offset + 2] & 0xff) << 16)
0559: | ((long) (bits[offset + 3] & 0xff) << 24)
0560: | ((long) (bits[offset + 4] & 0xff) << 32)
0561: | ((long) (bits[offset + 5] & 0xff) << 40)
0562: | ((long) (bits[offset + 6] & 0xff) << 48)
0563: | ((long) (bits[offset + 7] & 0xff) << 56);
0564:
0565: return Double.longBitsToDouble(valueAsLong);
0566: }
0567:
0568: public abstract double getNativeDouble(int columnIndex)
0569: throws SQLException;
0570:
0571: protected float getNativeFloat(byte[] bits, int offset) {
0572: int asInt = (bits[offset + 0] & 0xff)
0573: | ((bits[offset + 1] & 0xff) << 8)
0574: | ((bits[offset + 2] & 0xff) << 16)
0575: | ((bits[offset + 3] & 0xff) << 24);
0576:
0577: return Float.intBitsToFloat(asInt);
0578: }
0579:
0580: public abstract float getNativeFloat(int columnIndex)
0581: throws SQLException;
0582:
0583: protected int getNativeInt(byte[] bits, int offset) {
0584:
0585: int valueAsInt = (bits[offset + 0] & 0xff)
0586: | ((bits[offset + 1] & 0xff) << 8)
0587: | ((bits[offset + 2] & 0xff) << 16)
0588: | ((bits[offset + 3] & 0xff) << 24);
0589:
0590: return valueAsInt;
0591: }
0592:
0593: public abstract int getNativeInt(int columnIndex)
0594: throws SQLException;
0595:
0596: protected long getNativeLong(byte[] bits, int offset) {
0597: long valueAsLong = (bits[offset + 0] & 0xff)
0598: | ((long) (bits[offset + 1] & 0xff) << 8)
0599: | ((long) (bits[offset + 2] & 0xff) << 16)
0600: | ((long) (bits[offset + 3] & 0xff) << 24)
0601: | ((long) (bits[offset + 4] & 0xff) << 32)
0602: | ((long) (bits[offset + 5] & 0xff) << 40)
0603: | ((long) (bits[offset + 6] & 0xff) << 48)
0604: | ((long) (bits[offset + 7] & 0xff) << 56);
0605:
0606: return valueAsLong;
0607: }
0608:
0609: public abstract long getNativeLong(int columnIndex)
0610: throws SQLException;
0611:
0612: protected short getNativeShort(byte[] bits, int offset) {
0613: short asShort = (short) ((bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8));
0614:
0615: return asShort;
0616: }
0617:
0618: public abstract short getNativeShort(int columnIndex)
0619: throws SQLException;
0620:
0621: protected Time getNativeTime(int columnIndex, byte[] bits,
0622: int offset, int length, Calendar targetCalendar,
0623: TimeZone tz, boolean rollForward, ConnectionImpl conn,
0624: ResultSetImpl rs) throws SQLException {
0625:
0626: int hour = 0;
0627: int minute = 0;
0628: int seconds = 0;
0629:
0630: if (length != 0) {
0631: // bits[0] // skip tm->neg
0632: // binaryData.readLong(); // skip daysPart
0633: hour = bits[offset + 5];
0634: minute = bits[offset + 6];
0635: seconds = bits[offset + 7];
0636: }
0637:
0638: Calendar sessionCalendar = rs
0639: .getCalendarInstanceForSessionOrNew();
0640:
0641: synchronized (sessionCalendar) {
0642: Time time = TimeUtil.fastTimeCreate(sessionCalendar, hour,
0643: minute, seconds);
0644:
0645: Time adjustedTime = TimeUtil.changeTimezone(conn,
0646: sessionCalendar, targetCalendar, time, conn
0647: .getServerTimezoneTZ(), tz, rollForward);
0648:
0649: return adjustedTime;
0650: }
0651: }
0652:
0653: public abstract Time getNativeTime(int columnIndex,
0654: Calendar targetCalendar, TimeZone tz, boolean rollForward,
0655: ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
0656:
0657: protected Timestamp getNativeTimestamp(byte[] bits, int offset,
0658: int length, Calendar targetCalendar, TimeZone tz,
0659: boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
0660: throws SQLException {
0661: int year = 0;
0662: int month = 0;
0663: int day = 0;
0664:
0665: int hour = 0;
0666: int minute = 0;
0667: int seconds = 0;
0668:
0669: int nanos = 0;
0670:
0671: if (length != 0) {
0672: year = (bits[offset + 0] & 0xff)
0673: | ((bits[offset + 1] & 0xff) << 8);
0674: month = bits[2];
0675: day = bits[3];
0676:
0677: if (length > 4) {
0678: hour = bits[offset + 4];
0679: minute = bits[offset + 5];
0680: seconds = bits[offset + 6];
0681: }
0682:
0683: if (length > 7) {
0684: // MySQL uses microseconds
0685: nanos = ((bits[offset + 7] & 0xff)
0686: | ((bits[offset + 8] & 0xff) << 8)
0687: | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
0688: }
0689: }
0690:
0691: if ((year == 0) && (month == 0) && (day == 0)) {
0692: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
0693: .equals(conn.getZeroDateTimeBehavior())) {
0694:
0695: return null;
0696: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
0697: .equals(conn.getZeroDateTimeBehavior())) {
0698: throw SQLError
0699: .createSQLException(
0700: "Value '0000-00-00' can not be represented as java.sql.Timestamp",
0701: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0702: }
0703:
0704: year = 1;
0705: month = 1;
0706: day = 1;
0707: }
0708:
0709: Calendar sessionCalendar = conn
0710: .getUseJDBCCompliantTimezoneShift() ? conn
0711: .getUtcCalendar() : rs
0712: .getCalendarInstanceForSessionOrNew();
0713:
0714: synchronized (sessionCalendar) {
0715: Timestamp ts = rs.fastTimestampCreate(sessionCalendar,
0716: year, month, day, hour, minute, seconds, nanos);
0717:
0718: Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
0719: sessionCalendar, targetCalendar, ts, conn
0720: .getServerTimezoneTZ(), tz, rollForward);
0721:
0722: return adjustedTs;
0723: }
0724: }
0725:
0726: public abstract Timestamp getNativeTimestamp(int columnIndex,
0727: Calendar targetCalendar, TimeZone tz, boolean rollForward,
0728: ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
0729:
0730: public abstract Reader getReader(int columnIndex)
0731: throws SQLException;
0732:
0733: /**
0734: * Returns the value at the given column (index starts at 0) as a
0735: * java.lang.String with the requested encoding, using the given
0736: * ConnectionImpl to find character converters.
0737: *
0738: * @param index
0739: * of the column value (starting at 0) to return.
0740: * @param encoding
0741: * the Java name for the character encoding
0742: * @param conn
0743: * the connection that created this result set row
0744: *
0745: * @return the value for the given column (including NULL if it is) as a
0746: * String
0747: *
0748: * @throws SQLException
0749: * if an error occurs while retrieving the value.
0750: */
0751: public abstract String getString(int index, String encoding,
0752: ConnectionImpl conn) throws SQLException;
0753:
0754: /**
0755: * Convenience method for turning a byte[] into a string with the given
0756: * encoding.
0757: *
0758: * @param encoding
0759: * the Java encoding name for the byte[] -> char conversion
0760: * @param conn
0761: * the ConnectionImpl that created the result set
0762: * @param value
0763: * the String value as a series of bytes, encoded using
0764: * "encoding"
0765: * @param offset
0766: * where to start the decoding
0767: * @param length
0768: * how many bytes to decode
0769: *
0770: * @return the String as decoded from bytes with the given encoding
0771: *
0772: * @throws SQLException
0773: * if an error occurs
0774: */
0775: protected String getString(String encoding, ConnectionImpl conn,
0776: byte[] value, int offset, int length) throws SQLException {
0777: String stringVal = null;
0778:
0779: if ((conn != null) && conn.getUseUnicode()) {
0780: try {
0781: if (encoding == null) {
0782: stringVal = new String(value);
0783: } else {
0784: SingleByteCharsetConverter converter = conn
0785: .getCharsetConverter(encoding);
0786:
0787: if (converter != null) {
0788: stringVal = converter.toString(value, offset,
0789: length);
0790: } else {
0791: stringVal = new String(value, offset, length,
0792: encoding);
0793: }
0794: }
0795: } catch (java.io.UnsupportedEncodingException E) {
0796: throw SQLError
0797: .createSQLException(
0798: Messages
0799: .getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$
0800: + encoding + "'.", "0S100");
0801: }
0802: } else {
0803: stringVal = StringUtils
0804: .toAsciiString(value, offset, length);
0805: }
0806:
0807: return stringVal;
0808: }
0809:
0810: protected Time getTimeFast(int columnIndex, byte[] timeAsBytes,
0811: int offset, int length, Calendar targetCalendar,
0812: TimeZone tz, boolean rollForward, ConnectionImpl conn,
0813: ResultSetImpl rs) throws SQLException {
0814:
0815: int hr = 0;
0816: int min = 0;
0817: int sec = 0;
0818:
0819: try {
0820:
0821: if (timeAsBytes == null) {
0822: return null;
0823: }
0824:
0825: boolean allZeroTime = true;
0826: boolean onlyTimePresent = false;
0827:
0828: for (int i = 0; i < length; i++) {
0829: if (timeAsBytes[offset + i] == ':') {
0830: onlyTimePresent = true;
0831: break;
0832: }
0833: }
0834:
0835: for (int i = 0; i < length; i++) {
0836: byte b = timeAsBytes[offset + i];
0837:
0838: if (b == ' ' || b == '-' || b == '/') {
0839: onlyTimePresent = false;
0840: }
0841:
0842: if (b != '0' && b != ' ' && b != ':' && b != '-'
0843: && b != '/' && b != '.') {
0844: allZeroTime = false;
0845:
0846: break;
0847: }
0848: }
0849:
0850: if (!onlyTimePresent && allZeroTime) {
0851: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
0852: .equals(conn.getZeroDateTimeBehavior())) {
0853: return null;
0854: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
0855: .equals(conn.getZeroDateTimeBehavior())) {
0856: throw SQLError
0857: .createSQLException(
0858: "Value '"
0859: + new String(timeAsBytes)
0860: + "' can not be represented as java.sql.Time",
0861: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0862: }
0863:
0864: // We're left with the case of 'round' to a time Java _can_
0865: // represent, which is '00:00:00'
0866: return rs.fastTimeCreate(null, 0, 0, 0);
0867: }
0868:
0869: Field timeColField = this .metadata[columnIndex];
0870:
0871: if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
0872:
0873: switch (length) {
0874: case 19: { // YYYY-MM-DD hh:mm:ss
0875:
0876: hr = StringUtils.getInt(timeAsBytes, offset
0877: + length - 8, offset + length - 6);
0878: min = StringUtils.getInt(timeAsBytes, offset
0879: + length - 5, offset + length - 3);
0880: sec = StringUtils.getInt(timeAsBytes, offset
0881: + length - 2, offset + length);
0882: }
0883:
0884: break;
0885: case 14:
0886: case 12: {
0887: hr = StringUtils.getInt(timeAsBytes, offset
0888: + length - 6, offset + length - 4);
0889: min = StringUtils.getInt(timeAsBytes, offset
0890: + length - 4, offset + length - 2);
0891: sec = StringUtils.getInt(timeAsBytes, offset
0892: + length - 2, offset + length);
0893: }
0894:
0895: break;
0896:
0897: case 10: {
0898: hr = StringUtils.getInt(timeAsBytes, offset + 6,
0899: offset + 8);
0900: min = StringUtils.getInt(timeAsBytes, offset + 8,
0901: offset + 10);
0902: sec = 0;
0903: }
0904:
0905: break;
0906:
0907: default:
0908: throw SQLError
0909: .createSQLException(
0910: Messages
0911: .getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$
0912: + (columnIndex + 1)
0913: + "("
0914: + timeColField + ").",
0915: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0916: } /* endswitch */
0917:
0918: SQLWarning precisionLost = new SQLWarning(
0919: Messages
0920: .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
0921: + columnIndex
0922: + "("
0923: + timeColField
0924: + ").");
0925: /*
0926: * if (this.warningChain == null) { this.warningChain =
0927: * precisionLost; } else {
0928: * this.warningChain.setNextWarning(precisionLost); }
0929: */
0930: } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
0931: hr = StringUtils.getInt(timeAsBytes, offset + 11,
0932: offset + 13);
0933: min = StringUtils.getInt(timeAsBytes, offset + 14,
0934: offset + 16);
0935: sec = StringUtils.getInt(timeAsBytes, offset + 17,
0936: offset + 19);
0937:
0938: SQLWarning precisionLost = new SQLWarning(
0939: Messages
0940: .getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$
0941: + (columnIndex + 1)
0942: + "("
0943: + timeColField + ").");
0944:
0945: /*
0946: * if (this.warningChain == null) { this.warningChain =
0947: * precisionLost; } else {
0948: * this.warningChain.setNextWarning(precisionLost); }
0949: */
0950: } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
0951: return rs.fastTimeCreate(null, 0, 0, 0); // midnight on the
0952: // given
0953: // date
0954: } else {
0955: // convert a String to a Time
0956: if ((length != 5) && (length != 8)) {
0957: throw SQLError
0958: .createSQLException(
0959: Messages
0960: .getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$
0961: + new String(timeAsBytes)
0962: + Messages
0963: .getString("ResultSet.___in_column__268")
0964: + (columnIndex + 1),
0965: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0966: }
0967:
0968: hr = StringUtils.getInt(timeAsBytes, offset + 0,
0969: offset + 2);
0970: min = StringUtils.getInt(timeAsBytes, offset + 3,
0971: offset + 5);
0972: sec = (length == 5) ? 0 : StringUtils.getInt(
0973: timeAsBytes, offset + 6, offset + 8);
0974: }
0975:
0976: Calendar sessionCalendar = rs
0977: .getCalendarInstanceForSessionOrNew();
0978:
0979: synchronized (sessionCalendar) {
0980: return TimeUtil
0981: .changeTimezone(conn, sessionCalendar,
0982: targetCalendar, rs.fastTimeCreate(
0983: sessionCalendar, hr, min, sec),
0984: conn.getServerTimezoneTZ(), tz,
0985: rollForward);
0986: }
0987: } catch (Exception ex) {
0988: throw SQLError.createSQLException(ex.toString(),
0989: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0990: }
0991: }
0992:
0993: public abstract Time getTimeFast(int columnIndex,
0994: Calendar targetCalendar, TimeZone tz, boolean rollForward,
0995: ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
0996:
0997: protected Timestamp getTimestampFast(int columnIndex,
0998: byte[] timestampAsBytes, int offset, int length,
0999: Calendar targetCalendar, TimeZone tz, boolean rollForward,
1000: ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
1001:
1002: try {
1003: Calendar sessionCalendar = conn
1004: .getUseJDBCCompliantTimezoneShift() ? conn
1005: .getUtcCalendar() : rs
1006: .getCalendarInstanceForSessionOrNew();
1007:
1008: synchronized (sessionCalendar) {
1009: boolean allZeroTimestamp = true;
1010:
1011: boolean onlyTimePresent = false;
1012:
1013: for (int i = 0; i < length; i++) {
1014: if (timestampAsBytes[offset + i] == ':') {
1015: onlyTimePresent = true;
1016: break;
1017: }
1018: }
1019:
1020: for (int i = 0; i < length; i++) {
1021: byte b = timestampAsBytes[offset + i];
1022:
1023: if (b == ' ' || b == '-' || b == '/') {
1024: onlyTimePresent = false;
1025: }
1026:
1027: if (b != '0' && b != ' ' && b != ':' && b != '-'
1028: && b != '/' && b != '.') {
1029: allZeroTimestamp = false;
1030:
1031: break;
1032: }
1033: }
1034:
1035: if (!onlyTimePresent && allZeroTimestamp) {
1036:
1037: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
1038: .equals(conn.getZeroDateTimeBehavior())) {
1039:
1040: return null;
1041: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
1042: .equals(conn.getZeroDateTimeBehavior())) {
1043: throw SQLError
1044: .createSQLException(
1045: "Value '"
1046: + timestampAsBytes
1047: + "' can not be represented as java.sql.Timestamp",
1048: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1049: }
1050:
1051: // We're left with the case of 'round' to a date Java _can_
1052: // represent, which is '0001-01-01'.
1053: return rs.fastTimestampCreate(null, 1, 1, 1, 0, 0,
1054: 0, 0);
1055:
1056: } else if (this .metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
1057:
1058: return TimeUtil.changeTimezone(conn,
1059: sessionCalendar, targetCalendar, rs
1060: .fastTimestampCreate(
1061: sessionCalendar,
1062: StringUtils.getInt(
1063: timestampAsBytes,
1064: offset, 4), 1, 1,
1065: 0, 0, 0, 0), conn
1066: .getServerTimezoneTZ(), tz,
1067: rollForward);
1068:
1069: } else {
1070: if (timestampAsBytes[offset + length - 1] == '.') {
1071: length--;
1072: }
1073:
1074: // Convert from TIMESTAMP or DATE
1075: switch (length) {
1076: case 26:
1077: case 25:
1078: case 24:
1079: case 23:
1080: case 22:
1081: case 21:
1082: case 20:
1083: case 19: {
1084: int year = StringUtils.getInt(timestampAsBytes,
1085: offset + 0, offset + 4);
1086: int month = StringUtils.getInt(
1087: timestampAsBytes, offset + 5,
1088: offset + 7);
1089: int day = StringUtils.getInt(timestampAsBytes,
1090: offset + 8, offset + 10);
1091: int hour = StringUtils.getInt(timestampAsBytes,
1092: offset + 11, offset + 13);
1093: int minutes = StringUtils.getInt(
1094: timestampAsBytes, offset + 14,
1095: offset + 16);
1096: int seconds = StringUtils.getInt(
1097: timestampAsBytes, offset + 17,
1098: offset + 19);
1099:
1100: int nanos = 0;
1101:
1102: if (length > 19) {
1103: int decimalIndex = -1;
1104:
1105: for (int i = 0; i < length; i++) {
1106: if (timestampAsBytes[offset + i] == '.') {
1107: decimalIndex = i;
1108: }
1109: }
1110:
1111: if (decimalIndex != -1) {
1112: if ((decimalIndex + 2) <= length) {
1113: nanos = StringUtils.getInt(
1114: timestampAsBytes,
1115: decimalIndex + 1, offset
1116: + length);
1117: } else {
1118: throw new IllegalArgumentException(); // re-thrown
1119: // further
1120: // down
1121: // with
1122: // a
1123: // much better error message
1124: }
1125: }
1126: }
1127:
1128: return TimeUtil.changeTimezone(conn,
1129: sessionCalendar, targetCalendar,
1130: rs.fastTimestampCreate(sessionCalendar,
1131: year, month, day, hour,
1132: minutes, seconds, nanos), conn
1133: .getServerTimezoneTZ(), tz,
1134: rollForward);
1135: }
1136:
1137: case 14: {
1138: int year = StringUtils.getInt(timestampAsBytes,
1139: offset + 0, offset + 4);
1140: int month = StringUtils.getInt(
1141: timestampAsBytes, offset + 4,
1142: offset + 6);
1143: int day = StringUtils.getInt(timestampAsBytes,
1144: offset + 6, offset + 8);
1145: int hour = StringUtils.getInt(timestampAsBytes,
1146: offset + 8, offset + 10);
1147: int minutes = StringUtils.getInt(
1148: timestampAsBytes, offset + 10,
1149: offset + 12);
1150: int seconds = StringUtils.getInt(
1151: timestampAsBytes, offset + 12,
1152: offset + 14);
1153:
1154: return TimeUtil.changeTimezone(conn,
1155: sessionCalendar, targetCalendar, rs
1156: .fastTimestampCreate(
1157: sessionCalendar, year,
1158: month, day, hour,
1159: minutes, seconds, 0),
1160: conn.getServerTimezoneTZ(), tz,
1161: rollForward);
1162: }
1163:
1164: case 12: {
1165: int year = StringUtils.getInt(timestampAsBytes,
1166: offset + 0, offset + 2);
1167:
1168: if (year <= 69) {
1169: year = (year + 100);
1170: }
1171:
1172: int month = StringUtils.getInt(
1173: timestampAsBytes, offset + 2,
1174: offset + 4);
1175: int day = StringUtils.getInt(timestampAsBytes,
1176: offset + 4, offset + 6);
1177: int hour = StringUtils.getInt(timestampAsBytes,
1178: offset + 6, offset + 8);
1179: int minutes = StringUtils.getInt(
1180: timestampAsBytes, offset + 8,
1181: offset + 10);
1182: int seconds = StringUtils.getInt(
1183: timestampAsBytes, offset + 10,
1184: offset + 12);
1185:
1186: return TimeUtil.changeTimezone(conn,
1187: sessionCalendar, targetCalendar, rs
1188: .fastTimestampCreate(
1189: sessionCalendar,
1190: year + 1900, month,
1191: day, hour, minutes,
1192: seconds, 0), conn
1193: .getServerTimezoneTZ(), tz,
1194: rollForward);
1195: }
1196:
1197: case 10: {
1198: int year;
1199: int month;
1200: int day;
1201: int hour;
1202: int minutes;
1203:
1204: boolean hasDash = false;
1205:
1206: for (int i = 0; i < length; i++) {
1207: if (timestampAsBytes[offset + i] == '-') {
1208: hasDash = true;
1209: break;
1210: }
1211: }
1212:
1213: if ((this .metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
1214: || hasDash) {
1215: year = StringUtils.getInt(timestampAsBytes,
1216: offset + 0, offset + 4);
1217: month = StringUtils.getInt(
1218: timestampAsBytes, offset + 5,
1219: offset + 7);
1220: day = StringUtils.getInt(timestampAsBytes,
1221: offset + 8, offset + 10);
1222: hour = 0;
1223: minutes = 0;
1224: } else {
1225: year = StringUtils.getInt(timestampAsBytes,
1226: offset + 0, offset + 2);
1227:
1228: if (year <= 69) {
1229: year = (year + 100);
1230: }
1231:
1232: month = StringUtils.getInt(
1233: timestampAsBytes, offset + 2,
1234: offset + 4);
1235: day = StringUtils.getInt(timestampAsBytes,
1236: offset + 4, offset + 6);
1237: hour = StringUtils.getInt(timestampAsBytes,
1238: offset + 6, offset + 8);
1239: minutes = StringUtils.getInt(
1240: timestampAsBytes, offset + 8,
1241: offset + 10);
1242:
1243: year += 1900; // two-digit year
1244: }
1245:
1246: return TimeUtil.changeTimezone(conn,
1247: sessionCalendar, targetCalendar, rs
1248: .fastTimestampCreate(
1249: sessionCalendar, year,
1250: month, day, hour,
1251: minutes, 0, 0), conn
1252: .getServerTimezoneTZ(), tz,
1253: rollForward);
1254: }
1255:
1256: case 8: {
1257: boolean hasColon = false;
1258:
1259: for (int i = 0; i < length; i++) {
1260: if (timestampAsBytes[offset + i] == ':') {
1261: hasColon = true;
1262: break;
1263: }
1264: }
1265:
1266: if (hasColon) {
1267: int hour = StringUtils.getInt(
1268: timestampAsBytes, offset + 0,
1269: offset + 2);
1270: int minutes = StringUtils.getInt(
1271: timestampAsBytes, offset + 3,
1272: offset + 5);
1273: int seconds = StringUtils.getInt(
1274: timestampAsBytes, offset + 6,
1275: offset + 8);
1276:
1277: return TimeUtil.changeTimezone(conn,
1278: sessionCalendar, targetCalendar,
1279: rs.fastTimestampCreate(
1280: sessionCalendar, 1970, 1,
1281: 1, hour, minutes, seconds,
1282: 0), conn
1283: .getServerTimezoneTZ(), tz,
1284: rollForward);
1285:
1286: }
1287:
1288: int year = StringUtils.getInt(timestampAsBytes,
1289: offset + 0, offset + 4);
1290: int month = StringUtils.getInt(
1291: timestampAsBytes, offset + 4,
1292: offset + 6);
1293: int day = StringUtils.getInt(timestampAsBytes,
1294: offset + 6, offset + 8);
1295:
1296: return TimeUtil.changeTimezone(conn,
1297: sessionCalendar, targetCalendar, rs
1298: .fastTimestampCreate(
1299: sessionCalendar,
1300: year - 1900, month - 1,
1301: day, 0, 0, 0, 0), conn
1302: .getServerTimezoneTZ(), tz,
1303: rollForward);
1304: }
1305:
1306: case 6: {
1307: int year = StringUtils.getInt(timestampAsBytes,
1308: offset + 0, offset + 2);
1309:
1310: if (year <= 69) {
1311: year = (year + 100);
1312: }
1313:
1314: int month = StringUtils.getInt(
1315: timestampAsBytes, offset + 2,
1316: offset + 4);
1317: int day = StringUtils.getInt(timestampAsBytes,
1318: offset + 4, offset + 6);
1319:
1320: return TimeUtil.changeTimezone(conn,
1321: sessionCalendar, targetCalendar, rs
1322: .fastTimestampCreate(
1323: sessionCalendar,
1324: year + 1900, month,
1325: day, 0, 0, 0, 0), conn
1326: .getServerTimezoneTZ(), tz,
1327: rollForward);
1328: }
1329:
1330: case 4: {
1331: int year = StringUtils.getInt(timestampAsBytes,
1332: offset + 0, offset + 2);
1333:
1334: if (year <= 69) {
1335: year = (year + 100);
1336: }
1337:
1338: int month = StringUtils.getInt(
1339: timestampAsBytes, offset + 2,
1340: offset + 4);
1341:
1342: return TimeUtil.changeTimezone(conn,
1343: sessionCalendar, targetCalendar, rs
1344: .fastTimestampCreate(
1345: sessionCalendar,
1346: year + 1900, month, 1,
1347: 0, 0, 0, 0), conn
1348: .getServerTimezoneTZ(), tz,
1349: rollForward);
1350: }
1351:
1352: case 2: {
1353: int year = StringUtils.getInt(timestampAsBytes,
1354: offset + 0, offset + 2);
1355:
1356: if (year <= 69) {
1357: year = (year + 100);
1358: }
1359:
1360: return TimeUtil.changeTimezone(conn,
1361: sessionCalendar, targetCalendar, rs
1362: .fastTimestampCreate(null,
1363: year + 1900, 1, 1, 0,
1364: 0, 0, 0), conn
1365: .getServerTimezoneTZ(), tz,
1366: rollForward);
1367: }
1368:
1369: default:
1370: throw new java.sql.SQLException(
1371: "Bad format for Timestamp '"
1372: + new String(timestampAsBytes)
1373: + "' in column "
1374: + (columnIndex + 1) + ".",
1375: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1376: }
1377: }
1378: }
1379: } catch (Exception e) {
1380: throw new java.sql.SQLException("Cannot convert value '"
1381: + getString(columnIndex, "ISO8859_1", conn)
1382: + "' from column " + (columnIndex + 1)
1383: + " to TIMESTAMP.",
1384: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1385: }
1386: }
1387:
1388: public abstract Timestamp getTimestampFast(int columnIndex,
1389: Calendar targetCalendar, TimeZone tz, boolean rollForward,
1390: ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
1391:
1392: /**
1393: * Could the column value at the given index (which starts at 0) be
1394: * interpreted as a floating-point number (has +/-/E/e in it)?
1395: *
1396: * @param index
1397: * of the column value (starting at 0) to check.
1398: *
1399: * @return true if the column value at the given index looks like it might
1400: * be a floating-point number, false if not.
1401: *
1402: * @throws SQLException
1403: * if an error occurs
1404: */
1405: public abstract boolean isFloatingPointNumber(int index)
1406: throws SQLException;
1407:
1408: /**
1409: * Is the column value at the given index (which starts at 0) NULL?
1410: *
1411: * @param index
1412: * of the column value (starting at 0) to check.
1413: *
1414: * @return true if the column value is NULL, false if not.
1415: *
1416: * @throws SQLException
1417: * if an error occurs
1418: */
1419: public abstract boolean isNull(int index) throws SQLException;
1420:
1421: /**
1422: * Returns the length of the column at the given index (which starts at 0).
1423: *
1424: * @param index
1425: * of the column value (starting at 0) for which to return the
1426: * length.
1427: * @return the length of the requested column, 0 if null (clients of this
1428: * interface should use isNull() beforehand to determine status of
1429: * NULL values in the column).
1430: *
1431: * @throws SQLException
1432: */
1433: public abstract long length(int index) throws SQLException;
1434:
1435: /**
1436: * Sets the given column value (only works currently with
1437: * ByteArrayRowHolder).
1438: *
1439: * @param index
1440: * index of the column value (starting at 0) to set.
1441: * @param value
1442: * the (raw) value to set
1443: *
1444: * @throws SQLException
1445: * if an error occurs, or the concrete RowHolder doesn't support
1446: * this operation.
1447: */
1448: public abstract void setColumnValue(int index, byte[] value)
1449: throws SQLException;
1450:
1451: public void setMetadata(Field[] f) throws SQLException {
1452: this.metadata = f;
1453: }
1454: }
|